My Project
|
00001 #ifndef SQL_OPTIMIZER_INCLUDED 00002 #define SQL_OPTIMIZER_INCLUDED 00003 00004 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; version 2 of the License. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00018 00019 00022 /* 00023 This structure is used to collect info on potentially sargable 00024 predicates in order to check whether they become sargable after 00025 reading const tables. 00026 We form a bitmap of indexes that can be used for sargable predicates. 00027 Only such indexes are involved in range analysis. 00028 */ 00029 00030 #include "opt_explain_format.h" 00031 00032 typedef struct st_sargable_param 00033 { 00034 Field *field; /* field against which to check sargability */ 00035 Item **arg_value; /* values of potential keys for lookups */ 00036 uint num_values; /* number of values in the above array */ 00037 } SARGABLE_PARAM; 00038 00039 typedef struct st_rollup 00040 { 00041 enum State { STATE_NONE, STATE_INITED, STATE_READY }; 00042 State state; 00043 Item_null_array null_items; 00044 Ref_ptr_array *ref_pointer_arrays; 00045 List<Item> *fields; 00046 } ROLLUP; 00047 00048 class JOIN :public Sql_alloc 00049 { 00050 JOIN(const JOIN &rhs); 00051 JOIN& operator=(const JOIN &rhs); 00052 public: 00053 JOIN_TAB *join_tab,**best_ref; 00054 JOIN_TAB **map2table; 00055 TABLE **table; 00056 /* 00057 The table which has an index that allows to produce the requried ordering. 00058 A special value of 0x1 means that the ordering will be produced by 00059 passing 1st non-const table to filesort(). NULL means no such table exists. 00060 */ 00061 TABLE *sort_by_table; 00085 uint tables; 00086 uint primary_tables; 00087 uint const_tables; 00088 uint tmp_tables; 00089 uint send_group_parts; 00096 bool sort_and_group; 00097 bool first_record,full_join, no_field_update; 00098 bool group; 00099 bool do_send_rows; 00100 table_map all_table_map; 00101 table_map const_table_map; 00102 00108 table_map found_const_table_map; 00109 table_map outer_join; 00110 /* Number of records produced after join + group operation */ 00111 ha_rows send_records; 00112 ha_rows found_records,examined_rows,row_limit; 00113 // m_select_limit is used to decide if we are likely to scan the whole table. 00114 ha_rows m_select_limit; 00124 ha_rows fetch_limit; 00125 00130 ha_rows min_ft_matches; 00131 00132 /* Finally picked QEP. This is result of join optimization */ 00133 POSITION *best_positions; 00134 00135 /******* Join optimization state members start *******/ 00136 00137 /* Current join optimization state */ 00138 POSITION *positions; 00139 00140 /* We also maintain a stack of join optimization states in * join->positions[] */ 00141 /******* Join optimization state members end *******/ 00142 00143 00144 Next_select_func first_select; 00150 double best_read; 00154 ha_rows best_rowcount; 00155 List<Item> *fields; 00156 List<Cached_item> group_fields, group_fields_cache; 00157 THD *thd; 00158 Item_sum **sum_funcs, ***sum_funcs_end; 00160 Item_sum **sum_funcs2, ***sum_funcs_end2; 00161 ulonglong select_options; 00162 select_result *result; 00163 TMP_TABLE_PARAM tmp_table_param; 00164 MYSQL_LOCK *lock; 00166 SELECT_LEX_UNIT *unit; 00168 SELECT_LEX *select_lex; 00176 bool no_const_tables; 00177 00178 ROLLUP rollup; 00179 00180 bool select_distinct; 00181 00188 bool group_optimized_away; 00189 00190 /* 00191 simple_xxxxx is set if ORDER/GROUP BY doesn't include any references 00192 to other tables than the first non-constant table in the JOIN. 00193 It's also set if ORDER/GROUP BY is empty. 00194 Used for deciding for or against using a temporary table to compute 00195 GROUP/ORDER BY. 00196 */ 00197 bool simple_order, simple_group; 00198 00199 /* 00200 ordered_index_usage is set if an ordered index access 00201 should be used instead of a filesort when computing 00202 ORDER/GROUP BY. 00203 */ 00204 enum 00205 { 00206 ordered_index_void, // No ordered index avail. 00207 ordered_index_group_by, // Use index for GROUP BY 00208 ordered_index_order_by // Use index for ORDER BY 00209 } ordered_index_usage; 00210 00215 bool no_order; 00217 bool skip_sort_order; 00218 00219 bool need_tmp; 00220 int hidden_group_field_count; 00221 00222 Key_use_array keyuse; 00223 00224 List<Item> all_fields; 00225 00226 List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3; 00228 List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3; 00229 List<Item> &fields_list; 00230 List<Item> procedure_fields_list; 00231 int error; 00232 00240 class ORDER_with_src 00241 { 00253 struct null {}; 00254 00255 public: 00256 ORDER *order; //< ORDER expression that we are wrapping with this class 00257 Explain_sort_clause src; //< origin of order list 00258 00259 private: 00260 int flags; //< bitmap of Explain_sort_property 00261 00262 public: 00263 ORDER_with_src() { clean(); } 00264 00265 ORDER_with_src(ORDER *order_arg, Explain_sort_clause src_arg) 00266 : order(order_arg), src(src_arg), flags(order_arg ? ESP_EXISTS : ESP_none) 00267 {} 00268 00274 ORDER_with_src &operator=(null *) { clean(); return *this; } 00275 00281 ORDER_with_src(null *) { clean(); } 00282 00295 operator ORDER *() { return order; } 00296 operator const ORDER *() const { return order; } 00297 00298 ORDER* operator->() const { return order; } 00299 00300 void clean() { order= NULL; src= ESC_none; flags= ESP_none; } 00301 00302 void set_flag(Explain_sort_property flag) 00303 { 00304 DBUG_ASSERT(order); 00305 flags|= flag; 00306 } 00307 void reset_flag(Explain_sort_property flag) { flags&= ~flag; } 00308 bool get_flag(Explain_sort_property flag) const { 00309 DBUG_ASSERT(order); 00310 return flags & flag; 00311 } 00312 int get_flags() const { DBUG_ASSERT(order); return flags; } 00313 }; 00314 00318 ORDER_with_src order, group_list; 00319 00323 Explain_format_flags explain_flags; 00324 00342 Item *conds; 00343 Item *having; 00344 Item *having_for_explain; 00345 TABLE_LIST *tables_list; 00346 List<TABLE_LIST> *join_list; 00347 COND_EQUAL *cond_equal; 00348 /* 00349 Join tab to return to. Points to an element of join->join_tab array, or to 00350 join->join_tab[-1]. 00351 This is used at execution stage to shortcut join enumeration. Currently 00352 shortcutting is done to handle outer joins or handle semi-joins with 00353 FirstMatch strategy. 00354 */ 00355 JOIN_TAB *return_tab; 00356 00357 /* 00358 Used pointer reference for this select. 00359 select_lex->ref_pointer_array contains five "slices" of the same length: 00360 |========|========|========|========|========| 00361 ref_ptrs items0 items1 items2 items3 00362 */ 00363 Ref_ptr_array ref_ptrs; 00364 // Copy of the initial slice above, to be used with different lists 00365 Ref_ptr_array items0, items1, items2, items3; 00366 // Used by rollup, to restore ref_ptrs after overwriting it. 00367 Ref_ptr_array current_ref_ptrs; 00368 00369 const char *zero_result_cause; 00370 00371 bool union_part; 00372 bool optimized; 00373 00380 bool child_subquery_can_materialize; 00386 bool allow_outer_refs; 00387 00388 // true: No need to run DTORs on pointers. 00389 Mem_root_array<Item_exists_subselect*, true> sj_subselects; 00390 00391 /* Temporary tables used to weed-out semi-join duplicates */ 00392 List<TABLE> sj_tmp_tables; 00393 List<Semijoin_mat_exec> sjm_exec_list; 00394 /* end of allocation caching storage */ 00395 00397 bool set_group_rpa; 00399 bool group_sent; 00400 00401 JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, 00402 select_result *result_arg) 00403 : keyuse(thd_arg->mem_root), 00404 fields_list(fields_arg), 00405 sj_subselects(thd_arg->mem_root) 00406 { 00407 init(thd_arg, fields_arg, select_options_arg, result_arg); 00408 } 00409 00410 void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, 00411 select_result *result_arg) 00412 { 00413 join_tab= 0; 00414 tables= 0; 00415 primary_tables= 0; 00416 const_tables= 0; 00417 tmp_tables= 0; 00418 const_table_map= 0; 00419 join_list= 0; 00420 implicit_grouping= FALSE; 00421 sort_and_group= 0; 00422 first_record= 0; 00423 do_send_rows= 1; 00424 send_records= 0; 00425 found_records= 0; 00426 fetch_limit= HA_POS_ERROR; 00427 min_ft_matches= HA_POS_ERROR; 00428 examined_rows= 0; 00429 thd= thd_arg; 00430 sum_funcs= sum_funcs2= 0; 00431 having= having_for_explain= 0; 00432 select_options= select_options_arg; 00433 result= result_arg; 00434 lock= thd_arg->lock; 00435 select_lex= 0; //for safety 00436 select_distinct= MY_TEST(select_options & SELECT_DISTINCT); 00437 no_order= 0; 00438 simple_order= 0; 00439 simple_group= 0; 00440 ordered_index_usage= ordered_index_void; 00441 skip_sort_order= 0; 00442 need_tmp= 0; 00443 hidden_group_field_count= 0; /*safety*/ 00444 error= 0; 00445 return_tab= 0; 00446 ref_ptrs.reset(); 00447 items0.reset(); 00448 items1.reset(); 00449 items2.reset(); 00450 items3.reset(); 00451 zero_result_cause= 0; 00452 optimized= child_subquery_can_materialize= false; 00453 cond_equal= 0; 00454 group_optimized_away= 0; 00455 00456 all_fields= fields_arg; 00457 if (&fields_list != &fields_arg) /* Avoid valgrind-warning */ 00458 fields_list= fields_arg; 00459 keyuse.clear(); 00460 tmp_table_param.init(); 00461 tmp_table_param.end_write_records= HA_POS_ERROR; 00462 rollup.state= ROLLUP::STATE_NONE; 00463 00464 no_const_tables= FALSE; 00465 /* can help debugging (makes smaller test cases): */ 00466 DBUG_EXECUTE_IF("no_const_tables",no_const_tables= TRUE;); 00467 first_select= sub_select; 00468 set_group_rpa= false; 00469 group_sent= 0; 00470 } 00471 00473 bool plan_is_const() const { return const_tables == primary_tables; } 00474 00479 bool plan_is_single_table() { return primary_tables - const_tables == 1; } 00480 00481 int prepare(TABLE_LIST *tables, uint wind_num, 00482 Item *conds, uint og_num, ORDER *order, ORDER *group, 00483 Item *having, 00484 SELECT_LEX *select, SELECT_LEX_UNIT *unit); 00485 int optimize(); 00486 void reset(); 00487 void exec(); 00488 bool prepare_result(List<Item> **columns_list); 00489 bool explain(); 00490 bool destroy(); 00491 void restore_tmp(); 00492 bool alloc_func_list(); 00493 bool flatten_subqueries(); 00494 bool make_sum_func_list(List<Item> &all_fields, 00495 List<Item> &send_fields, 00496 bool before_group_by, bool recompute= FALSE); 00497 00499 Ref_ptr_array ref_ptr_array_slice(size_t slice_num) 00500 { 00501 size_t slice_sz= select_lex->ref_pointer_array.size() / 5U; 00502 DBUG_ASSERT(select_lex->ref_pointer_array.size() % 5 == 0); 00503 DBUG_ASSERT(slice_num < 5U); 00504 return Ref_ptr_array(&select_lex->ref_pointer_array[slice_num * slice_sz], 00505 slice_sz); 00506 } 00507 00513 void copy_ref_ptr_array(Ref_ptr_array dst_arr, Ref_ptr_array src_arr) 00514 { 00515 DBUG_ASSERT(dst_arr.size() >= src_arr.size()); 00516 void *dest= dst_arr.array(); 00517 const void *src= src_arr.array(); 00518 memcpy(dest, src, src_arr.size() * src_arr.element_size()); 00519 } 00520 00522 void set_items_ref_array(Ref_ptr_array src_arr) 00523 { 00524 copy_ref_ptr_array(ref_ptrs, src_arr); 00525 current_ref_ptrs= src_arr; 00526 } 00527 00529 void init_items_ref_array() 00530 { 00531 items0= ref_ptr_array_slice(1); 00532 copy_ref_ptr_array(items0, ref_ptrs); 00533 current_ref_ptrs= items0; 00534 } 00535 00536 bool rollup_init(); 00537 bool rollup_process_const_fields(); 00538 bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields, 00539 Item_sum ***func); 00540 int rollup_send_data(uint idx); 00541 int rollup_write_data(uint idx, TABLE *table); 00542 void remove_subq_pushed_predicates(Item **where); 00549 void join_free(); 00551 void cleanup(bool full); 00552 void clear(); 00553 bool save_join_tab(); 00554 void restore_join_tab(); 00555 bool init_save_join_tab(); 00566 bool send_row_on_empty_set() const 00567 { 00568 return (do_send_rows && tmp_table_param.sum_func_count != 0 && 00569 group_list == NULL && !group_optimized_away && 00570 select_lex->having_value != Item::COND_FALSE); 00571 } 00572 bool change_result(select_result *result); 00573 bool is_top_level_join() const 00574 { 00575 return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 || 00576 select_lex == unit->fake_select_lex)); 00577 } 00578 bool cache_const_exprs(); 00579 bool generate_derived_keys(); 00580 void drop_unused_derived_keys(); 00581 bool get_best_combination(); 00582 bool update_equalities_for_sjm(); 00583 bool add_sorting_to_table(JOIN_TAB *tab, ORDER_with_src *order); 00584 bool decide_subquery_strategy(); 00585 void refine_best_rowcount(); 00586 00587 private: 00593 void send_data(); 00594 00611 bool create_intermediate_table(JOIN_TAB *tab, List<Item> *tmp_table_fields, 00612 ORDER_with_src &tmp_table_group, 00613 bool save_sum_fields); 00618 bool create_first_intermediate_table(); 00625 void optimize_distinct(); 00626 00638 void optimize_fts_query(); 00639 00640 00644 void optimize_fts_limit_query(); 00645 00657 void replace_item_field(const char* field_name, Item* new_item); 00658 00659 #ifdef WITH_PARTITION_STORAGE_ENGINE 00660 bool prune_table_partitions(THD *thd); 00661 #endif 00662 00666 bool implicit_grouping; 00667 00668 void set_prefix_tables(); 00669 void cleanup_item_list(List<Item> &items) const; 00670 public: // @todo: Make private 00671 void set_semijoin_embedding(); 00672 private: 00673 void set_semijoin_info(); 00674 bool set_access_methods(); 00675 bool setup_materialized_table(JOIN_TAB *tab, uint tableno, 00676 const POSITION *inner_pos, 00677 POSITION *sjm_pos); 00678 bool add_having_as_tmp_table_cond(uint curr_tmp_table); 00679 bool make_tmp_tables_info(); 00680 bool compare_costs_of_subquery_strategies( 00681 Item_exists_subselect::enum_exec_method *method); 00682 00684 class Prepare_error_tracker 00685 { 00686 public: 00687 Prepare_error_tracker(THD *thd_arg) : thd(thd_arg) {} 00688 ~Prepare_error_tracker() 00689 { 00690 if (unlikely(thd->is_error())) 00691 thd->lex->mark_broken(); 00692 } 00693 private: 00694 THD *const thd; 00695 }; 00696 00697 }; 00698 00699 00700 bool uses_index_fields_only(Item *item, TABLE *tbl, uint keyno, 00701 bool other_tbls_ok); 00702 void update_depend_map(JOIN *join); 00703 void reset_nj_counters(List<TABLE_LIST> *join_list); 00704 Item *remove_eq_conds(THD *thd, Item *cond, Item::cond_result *cond_value); 00705 Item *optimize_cond(THD *thd, Item *conds, COND_EQUAL **cond_equal, 00706 List<TABLE_LIST> *join_list, 00707 bool build_equalities, Item::cond_result *cond_value); 00708 Item* substitute_for_best_equal_field(Item *cond, 00709 COND_EQUAL *cond_equal, 00710 void *table_join_idx); 00711 Item *build_equal_items(THD *thd, Item *cond, 00712 COND_EQUAL *inherited, bool do_inherit, 00713 List<TABLE_LIST> *join_list, 00714 COND_EQUAL **cond_equal_ref); 00715 bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args); 00716 Key_use_array *create_keyuse_for_table(THD *thd, TABLE *table, uint keyparts, 00717 Item_field **fields, 00718 List<Item> outer_exprs); 00719 Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field, 00720 bool *inherited_fl); 00721 Item_field *get_best_field(Item_field *item_field, COND_EQUAL *cond_equal); 00722 Item * 00723 make_cond_for_table(Item *cond, table_map tables, table_map used_table, 00724 bool exclude_expensive_cond); 00725 00732 inline bool field_time_cmp_date(const Field *f, const Item *v) 00733 { 00734 return f->is_temporal() && !f->is_temporal_with_date() && 00735 v->is_temporal_with_date(); 00736 } 00737 00738 #endif /* SQL_OPTIMIZER_INCLUDED */