Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use op codes to form query plan instead of using query path #4963

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion db/db_fingerprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ void add_fingerprint(struct sqlclntstate *clnt, sqlite3_stmt *stmt, struct strin
char *params = NULL;
int calc_query_plan = gbl_query_plans && !is_lua;
if (calc_query_plan) {
query_plan_ref = form_query_plan(clnt->query_stats);
query_plan_ref = form_query_plan(stmt);
calc_fingerprint(query_plan_ref ? string_ref_cstr(query_plan_ref) : NULL, &temp, plan_fingerprint);
if (gbl_sample_queries && param_count(clnt) > 0) {
// only get params string if we need it
Expand Down
40 changes: 28 additions & 12 deletions db/db_query_plan.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <math.h>
#include <ctrace.h>
#include <inttypes.h>
#include <sqlexplain.h>
#include <vdbeInt.h>

int gbl_query_plan_max_plans = 20;
extern double gbl_query_plan_percentage;
Expand All @@ -29,26 +31,40 @@ extern hash_t *gbl_fingerprint_hash;
extern pthread_mutex_t gbl_fingerprint_hash_mu;

// return NULL if no plan
struct string_ref *form_query_plan(const struct client_query_stats *query_stats)
struct string_ref *form_query_plan(sqlite3_stmt *stmt)
{
struct strbuf *query_plan_buf;
const struct client_query_path_component *c;
struct string_ref *query_plan_ref;
Op *op;
struct cursor_info c;
Vdbe *v = (Vdbe *)stmt;
char *operation;

if (query_stats->n_components == 0) {
if (!v)
return NULL;
}

query_plan_buf = strbuf_new();
for (int i = 0; i < query_stats->n_components; i++) {
if (i > 0) {
struct strbuf *query_plan_buf = strbuf_new();
for (int pc = 0; pc < v->nOp; pc++) {
op = &v->aOp[pc];
if (op->opcode == OP_OpenRead)
operation = "read";
else if (op->opcode == OP_ReopenIdx)
operation = "(re)read";
else if (op->opcode == OP_OpenRead_Record)
operation = "read";
else if (op->opcode == OP_OpenWrite)
operation = "write";
else
continue;

if (strbuf_len(query_plan_buf) > 0)
strbuf_append(query_plan_buf, ", ");
}
c = &query_stats->path_stats[i];
strbuf_appendf(query_plan_buf, "table %s index %d", c->table, c->ix);

strbuf_appendf(query_plan_buf, "open %s cursor on ", operation);
describe_cursor(v, pc, &c);
print_cursor_description(query_plan_buf, &c, 0);
}

query_plan_ref = create_string_ref((char *)strbuf_buf(query_plan_buf));
query_plan_ref = strbuf_len(query_plan_buf) > 0 ? create_string_ref((char *)strbuf_buf(query_plan_buf)) : NULL;
strbuf_free(query_plan_buf);
return query_plan_ref;
}
Expand Down
2 changes: 1 addition & 1 deletion db/sql.h
Original file line number Diff line number Diff line change
Expand Up @@ -1533,7 +1533,7 @@ struct query_plan_item {
};
int free_query_plan_hash(hash_t *query_plan_hash);
int clear_query_plans();
struct string_ref *form_query_plan(const struct client_query_stats *query_stats);
struct string_ref *form_query_plan(sqlite3_stmt *stmt);
void add_query_plan(int64_t cost, int64_t nrows, struct fingerprint_track *t, struct string_ref *zSql_ref,
struct string_ref *query_plan_ref, unsigned char *plan_fingerprint, char *params);

Expand Down
38 changes: 21 additions & 17 deletions db/sqlexplain.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static void print_field(Vdbe *v, struct cursor_info *cinfo, int num, char *buf)
}
}

static int print_cursor_description(strbuf *out, struct cursor_info *cinfo)
int print_cursor_description(strbuf *out, struct cursor_info *cinfo, int append_space)
{
struct schema *sc;
char scname[100];
Expand All @@ -189,10 +189,12 @@ static int print_cursor_description(strbuf *out, struct cursor_info *cinfo)
strbuf_appendf(out, "index ");
}
strbuf_appendf(out, "temp_%d", cinfo->tbl);
} else if (cinfo->tbl < 0) {
logmsg(LOGMSG_ERROR,"cinfo->tbl is less than 0!\n");
strbuf_append(out, "table \"???\"");
} else {
struct dbtable *db;

assert(cinfo->tbl >= 0);
db = thedb->dbs[cinfo->tbl];

if (cinfo->ix != -1) {
Expand Down Expand Up @@ -222,7 +224,8 @@ static int print_cursor_description(strbuf *out, struct cursor_info *cinfo)
}
strbuf_appendf(out, "table \"%s\"", db->tablename);
}
strbuf_appendf(out, " ");
if (append_space)
strbuf_appendf(out, " ");
return is_index;
}

Expand Down Expand Up @@ -366,7 +369,7 @@ static void affinity_to_text(char *aff, strbuf *out)

extern int sqlite3WhereTrace;

static void describe_cursor(Vdbe *v, int pc, struct cursor_info *cur)
void describe_cursor(Vdbe *v, int pc, struct cursor_info *cur)
{
Op *op = &v->aOp[pc];
bzero(cur, sizeof(struct cursor_info));
Expand All @@ -376,6 +379,7 @@ static void describe_cursor(Vdbe *v, int pc, struct cursor_info *cur)
if (db != NULL) {
cur->tbl = db->dbs_idx;
} else {
logmsg(LOGMSG_ERROR, "describe_cursor: db is NULL!\n");
cur->ix = -1;
cur->tbl = -1;
}
Expand Down Expand Up @@ -752,7 +756,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
print_field(v, &cur[op->p1], op->p2, buf); /* field name into buf */
strbuf_appendf(out, "R%d = %s from cursor [%d] on ", op->p3, buf,
op->p1);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
} else {
Op *colOp = &v->aOp[pc];
op = &v->aOp[pc_];
Expand Down Expand Up @@ -803,7 +807,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
case OP_Count:
strbuf_appendf(out, "R%d = select count(*) from cursor [%d] on ",
op->p2, op->p1);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
break;
case OP_Savepoint:
strbuf_appendf(
Expand Down Expand Up @@ -833,7 +837,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
describe_cursor(v, pc, &cur[op->p1]);
strbuf_appendf(out, "Open read cursor [%d] if not already open on ",
op->p1);
int is_index = print_cursor_description(out, &cur[op->p1]);
int is_index = print_cursor_description(out, &cur[op->p1], 1);
if (is_index && op->opcode == OP_OpenRead) {
if (op->p5 == 0xff) {
strbuf_append(out, "(not a covering index)");
Expand All @@ -848,7 +852,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
describe_cursor(v, pc, &cur[op->p1]);
strbuf_appendf(out, "Open %s cursor [%d] on ",
(op->opcode != OP_OpenWrite ? "read" : "write"), op->p1);
is_index = print_cursor_description(out, &cur[op->p1]);
is_index = print_cursor_description(out, &cur[op->p1], 1);
if (is_index && op->opcode == OP_OpenRead) {
if (op->p5 == 0xff) {
strbuf_append(out, "(not a covering index)");
Expand Down Expand Up @@ -961,13 +965,13 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
break;
case OP_Insert:
strbuf_appendf(out, "Write record in R%d into ", op->p2);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
strbuf_appendf(out, " using cursor [%d]", op->p1);
break;
case OP_Delete:
strbuf_appendf(out, "Delete current record from cursor [%d] on",
op->p1);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
break;
case OP_ResetCount:
strbuf_append(
Expand All @@ -976,7 +980,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
case OP_RowData:
strbuf_appendf(out, "R%d = key or data from cursor [%d] on ", op->p2,
op->p1);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
break;
case OP_Rowid:
strbuf_appendf(out, "R%d = genid of row pointed by cursor [%d]", op->p2,
Expand All @@ -987,7 +991,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
break;
case OP_Last:
strbuf_appendf(out, "Move cursor [%d] on ", op->p1);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
strbuf_append(out, "to last entry. ");
if (op->p2)
strbuf_appendf(out, "If no entries exist, go to %d", op->p2);
Expand Down Expand Up @@ -1018,7 +1022,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
break;
case OP_IdxInsert:
strbuf_appendf(out, "Write key in R%d into ", op->p2);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
strbuf_appendf(out, "using cursor [%d]", op->p1);
break;
case OP_IdxDelete:
Expand All @@ -1029,7 +1033,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
strbuf_appendf(out, "R%d", op->p2);
}
strbuf_appendf(out, " from ");
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
strbuf_appendf(out, "using cursor [%d]", op->p1);
break;
case OP_IdxRowid:
Expand All @@ -1052,11 +1056,11 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
break;
case OP_Destroy:
strbuf_append(out, "Destroy ");
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
break;
case OP_Clear:
strbuf_append(out, "Delete all rows from ");
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
break;
case OP_RowSetAdd:
strbuf_appendf(out, "Insert R%d into boolean index in R%d", op->p2,
Expand Down Expand Up @@ -1116,7 +1120,7 @@ void get_one_explain_line(sqlite3 *hndl, strbuf *out, Vdbe *v, int indent,
break;
case OP_CursorHint:
strbuf_appendf(out, "Cursor [%d] table ", op->p1);
print_cursor_description(out, &cur[op->p1]);
print_cursor_description(out, &cur[op->p1], 1);
char *descr = sqlite3ExprDescribe(hndl->pVdbe, op->p4.pExpr);
strbuf_appendf(out, " hint \"%s\"",
(descr) ? descr : "(expression not parseable, see 592)");
Expand Down
3 changes: 3 additions & 0 deletions db/sqlexplain.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ typedef struct {
void explain_data_prepare(IndentInfo *p, Vdbe *v);
void explain_data_delete(IndentInfo *p);

int print_cursor_description(strbuf *out, struct cursor_info *cinfo, int append_space);
void describe_cursor(Vdbe *v, int pc, struct cursor_info *cur);

#endif /* _SQLEXPLAIN_H_ */
8 changes: 4 additions & 4 deletions tests/fingerprints.test/t07.req.out
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
(a=29, b=30, c=31, d=32)
(a=33, b=34, c=35, d=36)
(a=37, b=38, c=39, d=40)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='6dc6fddfacf59d6af9b6ca29a1d1448d', normalized_sql='SELECT*FROM t2 WHERE a<?;', plan='table t2 index 0', total_cost_per_row=4.000000, num_executions=2, avg_cost_per_row=2.000000)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='70e60685f4bc838817d0490e36773f33', normalized_sql='SELECT*FROM t2 WHERE a<?;', plan='table t2 index -1', total_cost_per_row=3.500000, num_executions=1, avg_cost_per_row=3.500000)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='7342e5366727e8781044a411fd58d5b3', normalized_sql='SELECT*FROM t2 WHERE a<?;', plan='open read cursor on index "A" of table "t2"', total_cost_per_row=4.000000, num_executions=2, avg_cost_per_row=2.000000)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='1312f58a03a7afe964921b51794c5900', normalized_sql='SELECT*FROM t2 WHERE a<?;', plan='open read cursor on table "t2"', total_cost_per_row=3.500000, num_executions=1, avg_cost_per_row=3.500000)
(fingerprint='bb1b8ba88d815c2bac18af4618bae9dc', plan_fingerprint='00000000000000000000000000000000', normalized_sql='SELECT*FROM comdb2_query_plans WHERE fingerprint=?;', plan=NULL, total_cost_per_row=0.000000, num_executions=1, avg_cost_per_row=0.000000)
("test"='test', @test=1)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='6dc6fddfacf59d6af9b6ca29a1d1448d', query='select * from t2 where a < 40', query_plan='table t2 index 0', params=NULL)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='70e60685f4bc838817d0490e36773f33', query='select * from t2 where a < 40; // use worse query plan', query_plan='table t2 index -1', params=NULL)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='1312f58a03a7afe964921b51794c5900', query='select * from t2 where a < 40; // use worse query plan', query_plan='open read cursor on table "t2"', params=NULL)
(fingerprint='f57a9e3c17f13606af3630d8ebb27f3f', plan_fingerprint='7342e5366727e8781044a411fd58d5b3', query='select * from t2 where a < 40', query_plan='open read cursor on index "A" of table "t2"', params=NULL)
(fingerprint='bb1b8ba88d815c2bac18af4618bae9dc', plan_fingerprint='00000000000000000000000000000000', query='select * from comdb2_query_plans where fingerprint='f57a9e3c17f13606af3630d8ebb27f3f'', query_plan=NULL, params=NULL)
(fingerprint='ff590219c73ee93717a6aef16ee0dbe9', plan_fingerprint='00000000000000000000000000000000', query='select "test", @test', query_plan=NULL, params='[{"name":"test","type":"largeint","value":1}]')
("test"='test', 2=2)
Expand Down