!993 Fix issue: Fix a bug on the index advisor: bad type casting and strengthen the hypo-index

Merge pull request !993 from liuly/master
This commit is contained in:
opengauss-bot
2021-05-28 15:55:22 +08:00
committed by Gitee
3 changed files with 106 additions and 42 deletions

View File

@ -91,7 +91,8 @@ static void hypo_set_indexname(hypoIndex *entry, const char *indexname);
static void hypo_index_reset(void); static void hypo_index_reset(void);
static void hypo_injectHypotheticalIndex(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel, static void hypo_injectHypotheticalIndex(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel,
Relation relation, hypoIndex *entry); Relation relation, hypoIndex *entry);
static List *get_table_indexes(Oid oid);
static List *get_index_attrnum(Oid oid);
void InitHypopg() void InitHypopg()
{ {
@ -217,6 +218,31 @@ static void hypo_executorEnd_hook(QueryDesc *queryDesc)
standard_ExecutorEnd(queryDesc); standard_ExecutorEnd(queryDesc);
} }
} }
List *get_table_indexes(Oid oid)
{
Relation rel = heap_open(oid, NoLock);
List *indexes = RelationGetIndexList(rel);
heap_close(rel, NoLock);
return indexes;
}
/* Return the names of all the columns involved in the index. */
List *get_index_attrnum(Oid index_oid)
{
HeapTuple index_tup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
if (!HeapTupleIsValid(index_tup))
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("cache lookup failed for index %u", index_oid)));
Form_pg_index index_form = (Form_pg_index)GETSTRUCT(index_tup);
int2vector *attnums = &(index_form->indkey);
// get attrnum from table oid.
List *attrnum = NIL;
int i;
for (i = 0; i < attnums->dim1; i++) {
attrnum = lappend_int(attrnum, attnums->values[i]);
}
ReleaseSysCache(index_tup);
return attrnum;
}
/* /*
* This function will execute the "hypo_injectHypotheticalIndex" for every * This function will execute the "hypo_injectHypotheticalIndex" for every
@ -243,7 +269,32 @@ static void hypo_get_relation_info_hook(PlannerInfo *root, Oid relationObjectId,
* hypothetical index found, add it to the relation's * hypothetical index found, add it to the relation's
* indextlist * indextlist
*/ */
hypo_injectHypotheticalIndex(root, relationObjectId, inhparent, rel, relation, entry); List *indexes = get_table_indexes(entry->relid);
ListCell *index = NULL;
bool match_flag = false;
foreach (index, indexes) {
List *attrnums = get_index_attrnum(lfirst_oid(index));
if (attrnums == NIL) {
break;
}
if (entry->ncolumns > attrnums->length) {
continue;
}
match_flag = true;
for (int i = 0; i < entry->ncolumns; i++) {
if (entry->indexkeys[i] != list_nth_int(attrnums, i)) {
match_flag = false;
break;
}
}
// the suggested index has existed
if (match_flag) {
break;
}
}
if (!match_flag) {
hypo_injectHypotheticalIndex(root, relationObjectId, inhparent, rel, relation, entry);
}
} }
} }

View File

@ -906,6 +906,11 @@ void parse_join_expr(JoinExpr *join_tree)
return; return;
} }
if (nodeTag(join_tree->larg) != T_RangeVar ||
nodeTag(join_tree->rarg) != T_RangeVar) {
return;
}
List *join_fields = join_tree->usingClause; List *join_fields = join_tree->usingClause;
char *l_table_name = ((RangeVar *)(join_tree->larg))->relname; char *l_table_name = ((RangeVar *)(join_tree->larg))->relname;
char *r_table_name = ((RangeVar *)(join_tree->rarg))->relname; char *r_table_name = ((RangeVar *)(join_tree->rarg))->relname;
@ -1548,7 +1553,7 @@ void add_index_from_group_order(TableCell *table, List *clause, List *target_lis
ListCell *prev = NULL; ListCell *prev = NULL;
foreach (cur, table->index) { foreach (cur, table->index) {
IndexCell *table_index = (IndexCell *)lfirst(cur); IndexCell *table_index = (IndexCell *)lfirst(cur);
if (strcasecmp(table_index->index_name, index->index_name) == 0) { if (index->index_name == NULL || strcasecmp(table_index->index_name, index->index_name) == 0) {
break; break;
} }
if (table_index->op && strcasecmp(table_index->op, "=") != 0) { if (table_index->op && strcasecmp(table_index->op, "=") != 0) {

View File

@ -7,6 +7,8 @@ SQL_TYPE = ['select', 'delete', 'insert', 'update']
def output_valid_sql(sql): def output_valid_sql(sql):
if 'from pg_' in sql.lower():
return ''
if any(tp in sql.lower() for tp in SQL_TYPE[1:]): if any(tp in sql.lower() for tp in SQL_TYPE[1:]):
return sql if sql.endswith('; ') else sql + ';' return sql if sql.endswith('; ') else sql + ';'
elif SQL_TYPE[0] in sql.lower() and 'from ' in sql.lower(): elif SQL_TYPE[0] in sql.lower() and 'from ' in sql.lower():
@ -17,53 +19,59 @@ def output_valid_sql(sql):
def extract_sql_from_log(log_path): def extract_sql_from_log(log_path):
files = os.listdir(log_path) files = os.listdir(log_path)
for file in files: for file in files:
if not os.path.isdir(file) and '.swap' not in file: file_path = log_path + "/" + file
with open(log_path + "/" + file, mode='r') as f: if os.path.isfile(file_path) and re.search(r'.log$', file):
with open(file_path, mode='r') as f:
line = f.readline() line = f.readline()
sql = '' sql = ''
statement_flag = False statement_flag = False
execute_flag = False execute_flag = False
while line: while line:
# Identify statement scene try:
if re.search('statement: ', line, re.IGNORECASE): # Identify statement scene
statement_flag = True if re.search('statement: ', line, re.IGNORECASE):
if output_valid_sql(sql): statement_flag = True
yield output_valid_sql(sql) if output_valid_sql(sql):
sql = re.search(r'statement: (.*)', line.strip(), yield output_valid_sql(sql)
re.IGNORECASE).group(1) + ' ' sql = re.search(r'statement: (.*)', line.strip(),
line = f.readline() re.IGNORECASE).group(1) + ' '
line = f.readline()
# Identify execute statement scene # Identify execute statement scene
elif re.search(r'execute .*:', line, re.IGNORECASE): elif re.search(r'execute .*:', line, re.IGNORECASE):
if output_valid_sql(sql): if output_valid_sql(sql):
yield output_valid_sql(sql) yield output_valid_sql(sql)
execute_flag = True execute_flag = True
sql = re.search(r'execute .*: (.*)', line.strip(), re.IGNORECASE).group(1) sql = re.search(r'execute .*: (.*)', line.strip(), re.IGNORECASE).group(1)
line = f.readline() line = f.readline()
else: else:
if statement_flag: if statement_flag:
if re.match(r'^\t', line): if re.match(r'^\t', line):
sql += line.strip('\t\n') sql += line.strip('\t\n')
else:
statement_flag = False
if output_valid_sql(sql):
yield output_valid_sql(sql)
sql = ''
if execute_flag and re.search(r'parameters: ', line, re.IGNORECASE):
execute_flag = False
param_list = re.search(r'parameters: (.*)', line.strip(),
re.IGNORECASE).group(1).split(', ')
param_list = list(param.split('=', 1) for param in param_list)
param_list.sort(key=lambda x: int(x[0].strip(' $')),
reverse=True)
for item in param_list:
if len(item[1].strip()) >= 256:
sql = sql.replace(item[0].strip(), "''")
else: else:
sql = sql.replace(item[0].strip(), item[1].strip()) statement_flag = False
yield output_valid_sql(sql) if output_valid_sql(sql):
sql = '' yield output_valid_sql(sql)
sql = ''
if execute_flag and re.search(r'parameters: ', line, re.IGNORECASE):
execute_flag = False
param_list = re.search(r'parameters: (.*)', line.strip(),
re.IGNORECASE).group(1).split(', ')
param_list = list(param.split('=', 1) for param in param_list)
param_list.sort(key=lambda x: int(x[0].strip(' $')),
reverse=True)
for item in param_list:
if len(item[1].strip()) >= 256:
sql = sql.replace(item[0].strip(), "''")
else:
sql = sql.replace(item[0].strip(), item[1].strip())
yield output_valid_sql(sql)
sql = ''
line = f.readline()
except:
execute_flag = False
statement_flag = False
line = f.readline() line = f.readline()