mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
"Fix" for BUG #2050 "10 to 1 performance drop with server 4.1.1".
Actually it is not a bug but right behavior observed as pefomance degradation after we have forced Item_field::fix_fields() to re-execute each time when we are executing prep stmt. This patch implements small optimization which heals this bad behavior. We are caching field position in TABLE::field array in Item's member and are using this position for speeding up field lookups in fix_fields() in case of its re-execution.
This commit is contained in:
parent
b84a9dcf86
commit
9e28b7698d
8 changed files with 52 additions and 30 deletions
|
@ -26,6 +26,7 @@ bk@admin.bk
|
|||
bk@mysql.r18.ru
|
||||
carsten@tsort.bitbybit.dk
|
||||
davida@isil.mysql.com
|
||||
dlenev@brandersnatch.localdomain
|
||||
dlenev@build.mysql.com
|
||||
dlenev@mysql.com
|
||||
gerberb@ou800.zenez.com
|
||||
|
|
|
@ -105,7 +105,7 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
|||
const char *field_name_par)
|
||||
:changed_during_fix_field(0), db_name(db_name_par),
|
||||
table_name(table_name_par), field_name(field_name_par),
|
||||
depended_from(0)
|
||||
cached_field_index(-1), depended_from(0)
|
||||
{
|
||||
name = (char*) field_name_par;
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
|
|||
db_name(item->db_name),
|
||||
table_name(item->table_name),
|
||||
field_name(item->field_name),
|
||||
cached_field_index(item->cached_field_index),
|
||||
depended_from(item->depended_from)
|
||||
{}
|
||||
|
||||
|
|
|
@ -262,6 +262,11 @@ public:
|
|||
const char *db_name;
|
||||
const char *table_name;
|
||||
const char *field_name;
|
||||
/*
|
||||
Cached value of index for this field in table->field array, used by prep.
|
||||
stmts for speeding up their re-execution, -1 if index value is not known.
|
||||
*/
|
||||
int cached_field_index;
|
||||
st_select_lex *depended_from;
|
||||
Item_ident(const char *db_name_par,const char *table_name_par,
|
||||
const char *field_name_par);
|
||||
|
|
|
@ -558,7 +558,8 @@ extern const Field *not_found_field;
|
|||
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||
TABLE_LIST **where, bool report_error);
|
||||
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
|
||||
bool check_grant,bool allow_rowid);
|
||||
bool check_grant,bool allow_rowid,
|
||||
int *cached_field_index_ptr);
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/des.h>
|
||||
struct st_des_keyblock
|
||||
|
|
|
@ -2194,8 +2194,10 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
|||
DBUG_RETURN(-1);
|
||||
while ((column = column_iter++))
|
||||
{
|
||||
int unused_field_idx= -1;
|
||||
if (!find_field_in_table(thd,table,column->column.ptr(),
|
||||
column->column.length(),0,0))
|
||||
column->column.length(),0,0,
|
||||
&unused_field_idx))
|
||||
{
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0),
|
||||
column->column.c_ptr(), table_list->alias);
|
||||
|
|
|
@ -1790,33 +1790,44 @@ bool rm_temporary_table(enum db_type base, char *path)
|
|||
#define WRONG_GRANT (Field*) -1
|
||||
|
||||
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
|
||||
bool check_grants, bool allow_rowid)
|
||||
bool check_grants, bool allow_rowid,
|
||||
int *cached_field_index_ptr)
|
||||
{
|
||||
Field *field;
|
||||
if (table->name_hash.records)
|
||||
Field **field_ptr= 0, *field;
|
||||
int cached_field_index= *cached_field_index_ptr;
|
||||
|
||||
if (cached_field_index >= 0 && cached_field_index < table->fields &&
|
||||
!my_strcasecmp(system_charset_info,
|
||||
table->field[cached_field_index]->field_name, name))
|
||||
field_ptr= table->field + cached_field_index;
|
||||
else if (table->name_hash.records)
|
||||
field_ptr= (Field**)hash_search(&table->name_hash,(byte*) name,
|
||||
length);
|
||||
else
|
||||
{
|
||||
if ((field=(Field*) hash_search(&table->name_hash,(byte*) name,
|
||||
length)))
|
||||
goto found;
|
||||
if (!(field_ptr=table->field))
|
||||
return (Field *)0;
|
||||
while (*field_ptr)
|
||||
{
|
||||
if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name))
|
||||
break;
|
||||
++field_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_ptr && *field_ptr)
|
||||
{
|
||||
*cached_field_index_ptr= field_ptr - table->field;
|
||||
field= *field_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Field **ptr;
|
||||
if (!(ptr=table->field))
|
||||
return (Field *)0;
|
||||
while ((field = *ptr++))
|
||||
{
|
||||
if (!my_strcasecmp(system_charset_info, field->field_name, name))
|
||||
goto found;
|
||||
}
|
||||
if (!allow_rowid ||
|
||||
my_strcasecmp(system_charset_info, name, "_rowid") ||
|
||||
!(field=table->rowid_field))
|
||||
return (Field*) 0;
|
||||
}
|
||||
if (allow_rowid &&
|
||||
!my_strcasecmp(system_charset_info, name, "_rowid") &&
|
||||
(field=table->rowid_field))
|
||||
goto found;
|
||||
return (Field*) 0;
|
||||
|
||||
found:
|
||||
if (thd->set_query_id)
|
||||
{
|
||||
if (field->query_id != thd->query_id)
|
||||
|
@ -1895,7 +1906,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||
Field *find=find_field_in_table(thd,tables->table,name,length,
|
||||
test(tables->table->grant.
|
||||
want_privilege),
|
||||
1);
|
||||
1, &(item->cached_field_index));
|
||||
if (find)
|
||||
{
|
||||
(*where)= tables;
|
||||
|
@ -1952,7 +1963,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||
|
||||
Field *field=find_field_in_table(thd,tables->table,name,length,
|
||||
test(tables->table->grant.want_privilege),
|
||||
allow_rowid);
|
||||
allow_rowid, &(item->cached_field_index));
|
||||
if (field)
|
||||
{
|
||||
if (field == WRONG_GRANT)
|
||||
|
|
|
@ -30,11 +30,11 @@ static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
|
|||
static uint find_field(TABLE *form,uint start,uint length);
|
||||
|
||||
|
||||
static byte* get_field_name(Field *buff,uint *length,
|
||||
static byte* get_field_name(Field **buff,uint *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
{
|
||||
*length= (uint) strlen(buff->field_name);
|
||||
return (byte*) buff->field_name;
|
||||
*length= (uint) strlen((*buff)->field_name);
|
||||
return (byte*) (*buff)->field_name;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -479,7 +479,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
|||
if (outparam->timestamp_field == reg_field)
|
||||
outparam->timestamp_field_offset=i;
|
||||
if (use_hash)
|
||||
(void) my_hash_insert(&outparam->name_hash,(byte*) *field_ptr); // Will never fail
|
||||
(void) my_hash_insert(&outparam->name_hash,(byte*) field_ptr); // Will never fail
|
||||
}
|
||||
*field_ptr=0; // End marker
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ struct st_table {
|
|||
handler *file;
|
||||
Field **field; /* Pointer to fields */
|
||||
Field_blob **blob_field; /* Pointer to blob fields */
|
||||
HASH name_hash; /* hash of field names */
|
||||
/* hash of field names (contains pointers to elements of field array) */
|
||||
HASH name_hash;
|
||||
byte *record[2]; /* Pointer to records */
|
||||
byte *default_values; /* Default values for INSERT */
|
||||
byte *insert_values; /* used by INSERT ... UPDATE */
|
||||
|
|
Loading…
Add table
Reference in a new issue