Commit bdb66d24 authored by monty@narttu.mysql.fi's avatar monty@narttu.mysql.fi

ORDER BY optimization

Fixed new bug when reading field types
parent 030df25b
...@@ -1793,9 +1793,8 @@ print_field_types(MYSQL_RES *result) ...@@ -1793,9 +1793,8 @@ print_field_types(MYSQL_RES *result)
MYSQL_FIELD *field; MYSQL_FIELD *field;
while ((field = mysql_fetch_field(result))) while ((field = mysql_fetch_field(result)))
{ {
tee_fprintf(PAGER,"%s '%s' %d %d %d %d %d\n", tee_fprintf(PAGER,"'%s.%s.%s.%s' %d %d %d %d %d\n",
field->name, field->catalog, field->db, field->table, field->name,
field->table ? "" : field->table,
(int) field->type, (int) field->type,
field->length, field->max_length, field->length, field->max_length,
field->flags, field->decimals); field->flags, field->decimals);
......
...@@ -1207,6 +1207,10 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, ...@@ -1207,6 +1207,10 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->length= (uint) uint3korr(row->data[2]); field->length= (uint) uint3korr(row->data[2]);
field->type= (enum enum_field_types) (uchar) row->data[3][0]; field->type= (enum enum_field_types) (uchar) row->data[3][0];
field->catalog=(char*) "";
field->db= (char*) "";
field->catalog_length= 0;
field->db_length= 0;
field->org_table_length= field->table_length= lengths[0]; field->org_table_length= field->table_length= lengths[0];
field->name_length= lengths[1]; field->name_length= lengths[1];
...@@ -2883,7 +2887,7 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql) ...@@ -2883,7 +2887,7 @@ my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */ mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 6 : 5))) if (!(fields=read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7 : 5)))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
(uint) field_count,0, (uint) field_count,0,
......
...@@ -557,7 +557,7 @@ KEY StringField (FieldKey,StringVal(32)) ...@@ -557,7 +557,7 @@ KEY StringField (FieldKey,StringVal(32))
INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref FieldKey,LongField,StringField StringField 36 const 3 Using where; Using filesort 1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 3 Using where
SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
FieldKey LongVal StringVal FieldKey LongVal StringVal
1 0 2 1 0 2
......
...@@ -379,8 +379,8 @@ SQL_SELECT::~SQL_SELECT() ...@@ -379,8 +379,8 @@ SQL_SELECT::~SQL_SELECT()
#undef index // Fix for Unixware 7 #undef index // Fix for Unixware 7
QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc) QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc)
:dont_free(0),error(0),index(key_nr),max_used_key_length(0),head(table), :dont_free(0),error(0),index(key_nr),max_used_key_length(0),
it(ranges),range(0) used_key_parts(0), head(table), it(ranges),range(0)
{ {
if (!no_alloc) if (!no_alloc)
{ {
...@@ -2326,6 +2326,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key, ...@@ -2326,6 +2326,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
flag); flag);
set_if_bigger(quick->max_used_key_length,range->min_length); set_if_bigger(quick->max_used_key_length,range->min_length);
set_if_bigger(quick->max_used_key_length,range->max_length); set_if_bigger(quick->max_used_key_length,range->max_length);
set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
if (!range) // Not enough memory if (!range) // Not enough memory
return 1; return 1;
quick->ranges.push_back(range); quick->ranges.push_back(range);
......
...@@ -70,7 +70,7 @@ class QUICK_SELECT { ...@@ -70,7 +70,7 @@ class QUICK_SELECT {
public: public:
bool next,dont_free; bool next,dont_free;
int error; int error;
uint index,max_used_key_length; uint index, max_used_key_length, used_key_parts;
TABLE *head; TABLE *head;
handler *file; handler *file;
byte *record; byte *record;
......
...@@ -1697,7 +1697,7 @@ sys_var *find_sys_var(const char *str, uint length) ...@@ -1697,7 +1697,7 @@ sys_var *find_sys_var(const char *str, uint length)
int sql_set_variables(THD *thd, List<set_var_base> *var_list) int sql_set_variables(THD *thd, List<set_var_base> *var_list)
{ {
int error= 0; int error= 0;
List_iterator<set_var_base> it(*var_list); List_iterator_fast<set_var_base> it(*var_list);
set_var_base *var; set_var_base *var;
while ((var=it++)) while ((var=it++))
...@@ -1813,5 +1813,5 @@ int set_var_password::update(THD *thd) ...@@ -1813,5 +1813,5 @@ int set_var_password::update(THD *thd)
#ifdef __GNUC__ #ifdef __GNUC__
template class List<set_var_base>; template class List<set_var_base>;
template class List_iterator<set_var_base>; template class List_iterator_fast<set_var_base>;
#endif #endif
...@@ -6275,14 +6275,14 @@ is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part, ...@@ -6275,14 +6275,14 @@ is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part,
*/ */
static uint static uint
test_if_subkey(ORDER *order, TABLE *table, uint ref, key_map usable_keys) test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
key_map usable_keys)
{ {
uint nr; uint nr;
uint min_length= (uint) ~0; uint min_length= (uint) ~0;
uint best= MAX_KEY; uint best= MAX_KEY;
uint not_used; uint not_used;
KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part; KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part;
uint ref_key_parts= table->key_info[ref].key_parts;
KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts; KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts;
for (nr= 0; usable_keys; usable_keys>>= 1, nr++) for (nr= 0; usable_keys; usable_keys>>= 1, nr++)
...@@ -6317,10 +6317,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -6317,10 +6317,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
bool no_changes) bool no_changes)
{ {
int ref_key; int ref_key;
uint ref_key_parts;
TABLE *table=tab->table; TABLE *table=tab->table;
SQL_SELECT *select=tab->select; SQL_SELECT *select=tab->select;
key_map usable_keys; key_map usable_keys;
DBUG_ENTER("test_if_skip_sort_order"); DBUG_ENTER("test_if_skip_sort_order");
LINT_INIT(ref_key_parts);
/* Check which keys can be used to resolve ORDER BY */ /* Check which keys can be used to resolve ORDER BY */
usable_keys= ~(key_map) 0; usable_keys= ~(key_map) 0;
...@@ -6336,9 +6338,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -6336,9 +6338,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
ref_key= -1; ref_key= -1;
if (tab->ref.key >= 0) // Constant range in WHERE if (tab->ref.key >= 0) // Constant range in WHERE
ref_key=tab->ref.key; {
ref_key= tab->ref.key;
ref_key_parts= tab->ref.key_parts;
}
else if (select && select->quick) // Range found by opt_range else if (select && select->quick) // Range found by opt_range
ref_key=select->quick->index; {
ref_key= select->quick->index;
ref_key_parts= select->quick->used_key_parts;
}
if (ref_key >= 0) if (ref_key >= 0)
{ {
...@@ -6352,20 +6360,28 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -6352,20 +6360,28 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
/* /*
We come here when ref_key is not among usable_keys We come here when ref_key is not among usable_keys
*/ */
uint a; uint new_ref_key;
if ((a= test_if_subkey(order, table, ref_key, usable_keys)) < MAX_KEY) /*
If using index only read, only consider other possible index only
keys
*/
if (table->used_keys & (((key_map) 1 << ref_key)))
usable_keys|= table->used_keys;
if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
usable_keys)) < MAX_KEY)
{ {
/* Found key that can be used to retrieve data in sorted order */
if (tab->ref.key >= 0) if (tab->ref.key >= 0)
{ {
tab->ref.key= a; tab->ref.key= new_ref_key;
table->file->index_init(a); table->file->index_init(new_ref_key);
} }
else else
{ {
select->quick->index= a; select->quick->index= new_ref_key;
select->quick->init(); select->quick->init();
} }
ref_key= a; ref_key= new_ref_key;
} }
} }
/* Check if we get the rows in requested sorted order by using the key */ /* Check if we get the rows in requested sorted order by using the key */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment