#include <opt_range.h>
Inheritance diagram for SQL_SELECT:


Public Member Functions | |
| SQL_SELECT () | |
| ~SQL_SELECT () | |
| void | cleanup () |
| bool | check_quick (THD *thd, bool force_quick_range, ha_rows limit) |
| bool | skip_record () |
| int | test_quick_select (THD *thd, key_map keys, table_map prev_tables, ha_rows limit, bool force_quick_range) |
Public Attributes | |
| QUICK_SELECT_I * | quick |
| COND * | cond |
| TABLE * | head |
| IO_CACHE | file |
| ha_rows | records |
| double | read_time |
| key_map | quick_keys |
| key_map | needed_reg |
| table_map | const_tables |
| table_map | read_tables |
| bool | free_cond |
Definition at line 679 of file opt_range.h.
| SQL_SELECT::SQL_SELECT | ( | ) |
Definition at line 897 of file opt_range.cc.
References Bitmap< 64 >::clear_all(), file, my_b_clear, needed_reg, and quick_keys.
00897 :quick(0),cond(0),free_cond(0) 00898 { 00899 quick_keys.clear_all(); needed_reg.clear_all(); 00900 my_b_clear(&file); 00901 }
Here is the call graph for this function:

| SQL_SELECT::~SQL_SELECT | ( | ) |
Definition at line 918 of file opt_range.cc.
References cleanup().
00919 { 00920 cleanup(); 00921 }
Here is the call graph for this function:

Definition at line 695 of file opt_range.h.
References Bitmap< 64 >::set_all(), and test_quick_select().
Referenced by mysql_delete(), and prepare_simple_select().
00696 { 00697 key_map tmp; 00698 tmp.set_all(); 00699 return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0; 00700 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void SQL_SELECT::cleanup | ( | ) |
Definition at line 904 of file opt_range.cc.
References close_cached_file(), cond, file, free_cond, and quick.
Referenced by create_sort_index(), and ~SQL_SELECT().
00905 { 00906 delete quick; 00907 quick= 0; 00908 if (free_cond) 00909 { 00910 free_cond=0; 00911 delete cond; 00912 cond= 0; 00913 } 00914 close_cached_file(&file); 00915 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool SQL_SELECT::skip_record | ( | ) | [inline] |
Definition at line 701 of file opt_range.h.
References cond, and Item::val_int().
Referenced by find_all_keys(), flush_cached_records(), and mysql_delete().
Here is the call graph for this function:

Here is the caller graph for this function:

| int SQL_SELECT::test_quick_select | ( | THD * | thd, | |
| key_map | keys, | |||
| table_map | prev_tables, | |||
| ha_rows | limit, | |||
| bool | force_quick_range | |||
| ) |
Definition at line 2008 of file opt_range.cc.
References alloc_root(), PARAM::baseflag, Bitmap< 64 >::clear_all(), cond, const_tables, RANGE_OPT_PARAM::current_table, DBL_MAX, DBUG_ENTER, DBUG_EXECUTE, DBUG_PRINT, DBUG_RETURN, FALSE, st_table::file, fill_used_fields_bitmap(), find_shortest_key(), st_key::flags, st_table::force_index, free_root(), get_best_covering_ror_intersect(), get_best_disjunct_quick(), get_best_group_min_max(), get_best_ror_intersect(), get_index_only_read_time(), get_key_scans_params(), get_mm_tree(), HA_FULLTEXT, HA_POS_ERROR, HA_SPATIAL, handler::ha_table_flags(), head, PARAM::imerge_cost_buff_size, SEL_TREE::IMPOSSIBLE, QUICK_SELECT_I::init(), init_sql_alloc(), Bitmap< 64 >::intersect(), Bitmap< 64 >::is_clear_all(), TRP_ROR_INTERSECT::is_covering, base_list::is_empty(), Bitmap< 64 >::is_set(), Field::itMBR, Field::itRAW, SEL_TREE::KEY, PARAM::key, st_table::key_info, st_key::key_part, st_key::key_parts, st_table_share::key_parts, RANGE_OPT_PARAM::key_parts, RANGE_OPT_PARAM::key_parts_end, SEL_TREE::KEY_SMALLER, st_table_share::keys, RANGE_OPT_PARAM::keys, st_table::keys_in_use_for_query, LINT_INIT, TABLE_READ_PLAN::make_quick(), st_table::map, RANGE_OPT_PARAM::mem_root, SEL_TREE::merges, min, MYF, PARAM::needed_reg, needed_reg, NULL, RANGE_OPT_PARAM::old_root, RANGE_OPT_PARAM::prev_tables, print_quick(), quick, st_table::quick_condition_rows, quick_keys, TABLE_READ_PLAN::read_cost, read_tables, RANGE_OPT_PARAM::read_tables, read_time, RANGE_OPT_PARAM::real_keynr, TABLE_READ_PLAN::records, records, ha_statistics::records, RANGE_OPT_PARAM::remove_jump_scans, st_table::s, handler::scan_time(), set_if_smaller, SPECIAL_SAFE_MODE, specialflag, SQLCOM_DELETE, SQLCOM_UPDATE, handler::stats, RANGE_OPT_PARAM::table, test, RANGE_OPT_PARAM::thd, TIME_FOR_COMPARE, Bitmap< 64 >::to_ulonglong(), TRUE, SEL_TREE::type, st_table::used_keys, and RANGE_OPT_PARAM::using_real_indexes.
Referenced by check_quick(), get_quick_record_count(), test_if_quick_select(), and test_if_skip_sort_order().
02011 { 02012 uint idx; 02013 double scan_time; 02014 DBUG_ENTER("SQL_SELECT::test_quick_select"); 02015 DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", 02016 keys_to_use.to_ulonglong(), (ulong) prev_tables, 02017 (ulong) const_tables)); 02018 DBUG_PRINT("info", ("records: %lu", (ulong) head->file->stats.records)); 02019 delete quick; 02020 quick=0; 02021 needed_reg.clear_all(); 02022 quick_keys.clear_all(); 02023 if ((specialflag & SPECIAL_SAFE_MODE) && ! force_quick_range || 02024 !limit) 02025 DBUG_RETURN(0); /* purecov: inspected */ 02026 if (keys_to_use.is_clear_all()) 02027 DBUG_RETURN(0); 02028 records= head->file->stats.records; 02029 if (!records) 02030 records++; /* purecov: inspected */ 02031 scan_time= (double) records / TIME_FOR_COMPARE + 1; 02032 read_time= (double) head->file->scan_time() + scan_time + 1.1; 02033 if (head->force_index) 02034 scan_time= read_time= DBL_MAX; 02035 if (limit < records) 02036 read_time= (double) records + scan_time + 1; // Force to use index 02037 else if (read_time <= 2.0 && !force_quick_range) 02038 DBUG_RETURN(0); /* No need for quick select */ 02039 02040 DBUG_PRINT("info",("Time to scan table: %g", read_time)); 02041 02042 keys_to_use.intersect(head->keys_in_use_for_query); 02043 if (!keys_to_use.is_clear_all()) 02044 { 02045 MEM_ROOT alloc; 02046 SEL_TREE *tree= NULL; 02047 KEY_PART *key_parts; 02048 KEY *key_info; 02049 PARAM param; 02050 02051 /* set up parameter that is passed to all functions */ 02052 param.thd= thd; 02053 param.baseflag=head->file->ha_table_flags(); 02054 param.prev_tables=prev_tables | const_tables; 02055 param.read_tables=read_tables; 02056 param.current_table= head->map; 02057 param.table=head; 02058 param.keys=0; 02059 param.mem_root= &alloc; 02060 param.old_root= thd->mem_root; 02061 param.needed_reg= &needed_reg; 02062 param.imerge_cost_buff_size= 0; 02063 param.using_real_indexes= TRUE; 02064 param.remove_jump_scans= TRUE; 02065 02066 thd->no_errors=1; // Don't warn about NULL 02067 init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); 02068 if (!(param.key_parts= (KEY_PART*) alloc_root(&alloc, 02069 sizeof(KEY_PART)* 02070 head->s->key_parts)) || 02071 fill_used_fields_bitmap(¶m)) 02072 { 02073 thd->no_errors=0; 02074 free_root(&alloc,MYF(0)); // Return memory & allocator 02075 DBUG_RETURN(0); // Can't use range 02076 } 02077 key_parts= param.key_parts; 02078 thd->mem_root= &alloc; 02079 02080 /* 02081 Make an array with description of all key parts of all table keys. 02082 This is used in get_mm_parts function. 02083 */ 02084 key_info= head->key_info; 02085 for (idx=0 ; idx < head->s->keys ; idx++, key_info++) 02086 { 02087 KEY_PART_INFO *key_part_info; 02088 if (!keys_to_use.is_set(idx)) 02089 continue; 02090 if (key_info->flags & HA_FULLTEXT) 02091 continue; // ToDo: ft-keys in non-ft ranges, if possible SerG 02092 02093 param.key[param.keys]=key_parts; 02094 key_part_info= key_info->key_part; 02095 for (uint part=0 ; part < key_info->key_parts ; 02096 part++, key_parts++, key_part_info++) 02097 { 02098 key_parts->key= param.keys; 02099 key_parts->part= part; 02100 key_parts->length= key_part_info->length; 02101 key_parts->store_length= key_part_info->store_length; 02102 key_parts->field= key_part_info->field; 02103 key_parts->null_bit= key_part_info->null_bit; 02104 key_parts->image_type = 02105 (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW; 02106 } 02107 param.real_keynr[param.keys++]=idx; 02108 } 02109 param.key_parts_end=key_parts; 02110 02111 /* Calculate cost of full index read for the shortest covering index */ 02112 if (!head->used_keys.is_clear_all()) 02113 { 02114 int key_for_use= find_shortest_key(head, &head->used_keys); 02115 double key_read_time= (get_index_only_read_time(¶m, records, 02116 key_for_use) + 02117 (double) records / TIME_FOR_COMPARE); 02118 DBUG_PRINT("info", ("'all'+'using index' scan will be using key %d, " 02119 "read time %g", key_for_use, key_read_time)); 02120 if (key_read_time < read_time) 02121 read_time= key_read_time; 02122 } 02123 02124 TABLE_READ_PLAN *best_trp= NULL; 02125 TRP_GROUP_MIN_MAX *group_trp; 02126 double best_read_time= read_time; 02127 02128 if (cond) 02129 { 02130 if ((tree= get_mm_tree(¶m,cond))) 02131 { 02132 if (tree->type == SEL_TREE::IMPOSSIBLE) 02133 { 02134 records=0L; /* Return -1 from this function. */ 02135 read_time= (double) HA_POS_ERROR; 02136 goto free_mem; 02137 } 02138 /* 02139 If the tree can't be used for range scans, proceed anyway, as we 02140 can construct a group-min-max quick select 02141 */ 02142 if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER) 02143 tree= NULL; 02144 } 02145 } 02146 02147 /* 02148 Try to construct a QUICK_GROUP_MIN_MAX_SELECT. 02149 Notice that it can be constructed no matter if there is a range tree. 02150 */ 02151 group_trp= get_best_group_min_max(¶m, tree); 02152 if (group_trp) 02153 { 02154 param.table->quick_condition_rows= min(group_trp->records, 02155 head->file->stats.records); 02156 if (group_trp->read_cost < best_read_time) 02157 { 02158 best_trp= group_trp; 02159 best_read_time= best_trp->read_cost; 02160 } 02161 } 02162 02163 if (tree) 02164 { 02165 /* 02166 It is possible to use a range-based quick select (but it might be 02167 slower than 'all' table scan). 02168 */ 02169 if (tree->merges.is_empty()) 02170 { 02171 TRP_RANGE *range_trp; 02172 TRP_ROR_INTERSECT *rori_trp; 02173 bool can_build_covering= FALSE; 02174 02175 /* Get best 'range' plan and prepare data for making other plans */ 02176 if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE, 02177 best_read_time))) 02178 { 02179 best_trp= range_trp; 02180 best_read_time= best_trp->read_cost; 02181 } 02182 02183 /* 02184 Simultaneous key scans and row deletes on several handler 02185 objects are not allowed so don't use ROR-intersection for 02186 table deletes. 02187 */ 02188 if ((thd->lex->sql_command != SQLCOM_DELETE)) 02189 #ifdef NOT_USED 02190 if ((thd->lex->sql_command != SQLCOM_UPDATE)) 02191 #endif 02192 { 02193 /* 02194 Get best non-covering ROR-intersection plan and prepare data for 02195 building covering ROR-intersection. 02196 */ 02197 if ((rori_trp= get_best_ror_intersect(¶m, tree, best_read_time, 02198 &can_build_covering))) 02199 { 02200 best_trp= rori_trp; 02201 best_read_time= best_trp->read_cost; 02202 /* 02203 Try constructing covering ROR-intersect only if it looks possible 02204 and worth doing. 02205 */ 02206 if (!rori_trp->is_covering && can_build_covering && 02207 (rori_trp= get_best_covering_ror_intersect(¶m, tree, 02208 best_read_time))) 02209 best_trp= rori_trp; 02210 } 02211 } 02212 } 02213 else 02214 { 02215 /* Try creating index_merge/ROR-union scan. */ 02216 SEL_IMERGE *imerge; 02217 TABLE_READ_PLAN *best_conj_trp= NULL, *new_conj_trp; 02218 LINT_INIT(new_conj_trp); /* no empty index_merge lists possible */ 02219 DBUG_PRINT("info",("No range reads possible," 02220 " trying to construct index_merge")); 02221 List_iterator_fast<SEL_IMERGE> it(tree->merges); 02222 while ((imerge= it++)) 02223 { 02224 new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time); 02225 if (new_conj_trp) 02226 set_if_smaller(param.table->quick_condition_rows, 02227 new_conj_trp->records); 02228 if (!best_conj_trp || (new_conj_trp && new_conj_trp->read_cost < 02229 best_conj_trp->read_cost)) 02230 best_conj_trp= new_conj_trp; 02231 } 02232 if (best_conj_trp) 02233 best_trp= best_conj_trp; 02234 } 02235 } 02236 02237 thd->mem_root= param.old_root; 02238 02239 /* If we got a read plan, create a quick select from it. */ 02240 if (best_trp) 02241 { 02242 records= best_trp->records; 02243 if (!(quick= best_trp->make_quick(¶m, TRUE)) || quick->init()) 02244 { 02245 delete quick; 02246 quick= NULL; 02247 } 02248 } 02249 02250 free_mem: 02251 free_root(&alloc,MYF(0)); // Return memory & allocator 02252 thd->mem_root= param.old_root; 02253 thd->no_errors=0; 02254 } 02255 02256 DBUG_EXECUTE("info", print_quick(quick, &needed_reg);); 02257 02258 /* 02259 Assume that if the user is using 'limit' we will only need to scan 02260 limit rows if we are using a key 02261 */ 02262 DBUG_RETURN(records ? test(quick) : -1); 02263 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 682 of file opt_range.h.
Referenced by add_ref_to_table_cond(), cleanup(), JOIN::exec(), find_all_keys(), get_all_items_for_category(), init_read_record(), make_select(), search_categories(), search_keyword(), search_topics(), select_describe(), skip_record(), and test_quick_select().
Definition at line 684 of file opt_range.h.
Referenced by cleanup(), init_read_record(), make_select(), and SQL_SELECT().
Definition at line 683 of file opt_range.h.
Referenced by get_quick_record_count(), make_select(), and test_quick_select().
Definition at line 681 of file opt_range.h.
Referenced by cleanup(), create_sort_index(), end_send(), error_if_full_join(), filesort(), find_all_keys(), flush_cached_records(), get_quick_record_count(), init_read_record(), st_join_table::is_using_loose_index_scan(), join_init_read_record(), make_join_readinfo(), mysql_delete(), prepare_simple_select(), rr_quick(), select_describe(), test_if_quick_select(), test_if_skip_sort_order(), and test_quick_select().
| double SQL_SELECT::read_time |
1.4.7

