MySQL 9.1.0
Source Code Documentation
|
Namespaces | |
namespace | anonymous_namespace{sql_select.cc} |
Classes | |
class | Plan_change_watchdog |
It is not obvious to see that test_if_skip_sort_order() never changes the plan if no_changes is true. More... | |
class | COND_CMP |
Macros | |
#define | KEY_OPTIMIZE_EXISTS 1 |
#define | KEY_OPTIMIZE_REF_OR_NULL 2 |
Typedefs | |
using | Global_tables_iterator = IntrusiveListIterator< Table_ref, &Table_ref::next_global > |
using | Global_tables_list = IteratorContainer< Global_tables_iterator > |
A list interface over the Table_ref::next_global pointer. More... | |
Functions | |
static bool | optimize_semijoin_nests_for_materialization (JOIN *join) |
Optimize semi-join nests that could be run with sj-materialization. More... | |
static void | calculate_materialization_costs (JOIN *join, Table_ref *sj_nest, uint n_tables, Semijoin_mat_optimize *sjm) |
For {semijoin,subquery} materialization: calculates various cost information, based on a plan in join->best_positions covering the to-be-materialized query block and only this. More... | |
static bool | make_join_query_block (JOIN *join, Item *cond) |
Separates the predicates in a join condition and pushes them to the join step where all involved tables are available in the join prefix. More... | |
static bool | list_contains_unique_index (JOIN_TAB *tab, bool(*find_func)(Field *, void *), void *data) |
Check if GROUP BY/DISTINCT can be optimized away because the set is already known to be distinct. More... | |
static bool | find_field_in_item_list (Field *field, void *data) |
Helper function for list_contains_unique_index. More... | |
static bool | find_field_in_order_list (Field *field, void *data) |
Helper function for list_contains_unique_index. More... | |
static TABLE * | get_sort_by_table (ORDER *a, ORDER *b, Table_ref *tables) |
Return table number if there is only one table in sort order and group and order is compatible, else return 0. More... | |
static void | trace_table_dependencies (Opt_trace_context *trace, JOIN_TAB *join_tabs, uint table_count) |
Writes to the optimizer trace information about dependencies between tables. More... | |
static bool | update_ref_and_keys (THD *thd, Key_use_array *keyuse, JOIN_TAB *join_tab, uint tables, Item *cond, table_map normal_tables, Query_block *query_block, SARGABLE_PARAM **sargables) |
Update keyuse array with all possible keys we can use to fetch rows. More... | |
static bool | pull_out_semijoin_tables (JOIN *join) |
Pull tables out of semi-join nests based on functional dependencies. More... | |
static void | add_loose_index_scan_and_skip_scan_keys (JOIN *join, JOIN_TAB *join_tab) |
Discover the indexes that might be used for GROUP BY or DISTINCT queries or indexes that might be used for SKIP SCAN. More... | |
static ha_rows | get_quick_record_count (THD *thd, JOIN_TAB *tab, ha_rows limit, Item *condition) |
Returns estimated number of rows that could be fetched by given access method. More... | |
static bool | only_eq_ref_tables (JOIN *join, ORDER *order, table_map tables, table_map *cached_eq_ref_tables, table_map *eq_ref_tables) |
static bool | setup_join_buffering (JOIN_TAB *tab, JOIN *join, uint no_jbuf_after) |
Set up join buffering for a specified table, if possible. More... | |
static bool | test_if_skip_sort_order (JOIN_TAB *tab, ORDER_with_src &order, ha_rows select_limit, const bool no_changes, const Key_map *map, int *order_idx) |
Test if we can skip ordering by using an index. More... | |
static Item_func_match * | test_if_ft_index_order (ORDER *order) |
Test if ORDER BY is a single MATCH function(ORDER BY MATCH) and sort order is descending. More... | |
static uint32 | get_key_length_tmp_table (Item *item) |
(end of group Query_Optimizer) More... | |
static bool | can_switch_from_ref_to_range (THD *thd, JOIN_TAB *tab, enum_order ordering, bool recheck_range) |
A helper function to check whether it's better to use range than ref. More... | |
static bool | has_not_null_predicate (Item *cond, Item_field *not_null_item) |
Check all existing AND'ed predicates in 'cond' for an existing 'is not null 'not_null_item''-predicate. More... | |
static void | SaveCondEqualLists (COND_EQUAL *cond_equal) |
The List<Item_multi_eq> in COND_EQUAL partially overlaps with the argument list in various Item_cond via C-style casts. More... | |
bool | substitute_gc (THD *thd, Query_block *query_block, Item *where_cond, ORDER *group_list, ORDER *order) |
Substitute all expressions in the WHERE condition and ORDER/GROUP lists that match generated columns (GC) expressions with GC fields, if any. More... | |
bool | is_prefix_index (TABLE *table, uint idx) |
Test if this is a prefix index. More... | |
int | test_if_order_by_key (ORDER_with_src *order_src, TABLE *table, uint idx, uint *used_key_parts, bool *skip_quick) |
Test if one can use the key to resolve ordering. More... | |
uint | find_shortest_key (TABLE *table, const Key_map *usable_keys) |
Find shortest key suitable for full table scan. More... | |
bool | is_subkey (KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part, KEY_PART_INFO *ref_key_part_end) |
Test if a second key is the subkey of the first one. More... | |
static bool | is_ref_or_null_optimized (const JOIN_TAB *tab, uint ref_key) |
Test if REF_OR_NULL optimization will be used if the specified ref_key is used for REF-access to 'tab'. More... | |
static uint | test_if_subkey (ORDER_with_src *order, JOIN_TAB *tab, uint ref, uint ref_key_parts, const Key_map *usable_keys) |
Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting. More... | |
static JOIN_TAB * | alloc_jtab_array (THD *thd, uint table_count) |
static void | revise_cache_usage (JOIN_TAB *join_tab) |
Item_multi_eq * | find_item_equal (COND_EQUAL *cond_equal, const Item_field *item_field, bool *inherited_fl) |
Find the multiple equality predicate containing a field. More... | |
Item_field * | get_best_field (Item_field *item_field, COND_EQUAL *cond_equal) |
Get the best field substitution for a given field. More... | |
static bool | check_simple_equality (THD *thd, Item *left_item, Item *right_item, Item *item, COND_EQUAL *cond_equal, bool *simple_equality) |
Check whether an equality can be used to build multiple equalities. More... | |
static bool | check_row_equality (THD *thd, Item *left_row, Item_row *right_row, COND_EQUAL *cond_equal, List< Item > *eq_list, bool *simple_equality) |
Convert row equalities into a conjunction of regular equalities. More... | |
static bool | check_equality (THD *thd, Item *item, COND_EQUAL *cond_equal, List< Item > *eq_list, bool *equality) |
Eliminate row equalities and form multiple equalities predicates. More... | |
static bool | build_equal_items_for_cond (THD *thd, Item *cond, Item **retcond, COND_EQUAL *inherited, bool do_inherit) |
Replace all equality predicates in a condition by multiple equality items. More... | |
static bool | build_equal_items (THD *thd, Item *cond, Item **retcond, COND_EQUAL *inherited, bool do_inherit, mem_root_deque< Table_ref * > *join_list, COND_EQUAL **cond_equal_ref) |
Build multiple equalities for a WHERE condition and all join conditions that inherit these multiple equalities. More... | |
static int | compare_fields_by_table_order (Item_field *field1, Item_field *field2, JOIN_TAB **table_join_idx) |
Compare field items by table order in the execution plan. More... | |
static Item * | eliminate_item_equal (THD *thd, Item *cond, COND_EQUAL *upper_levels, Item_multi_eq *item_equal) |
Generate minimal set of simple equalities equivalent to a multiple equality. More... | |
Item * | substitute_for_best_equal_field (THD *thd, Item *cond, COND_EQUAL *cond_equal, JOIN_TAB **table_join_idx) |
Substitute every field reference in a condition by the best equal field and eliminate all multiple equality predicates. More... | |
static bool | change_cond_ref_to_const (THD *thd, I_List< COND_CMP > *save_list, Item *and_father, Item *cond, Item *field, Item *value) |
change field = field to field = const for each found field = const in the and_level More... | |
static bool | propagate_cond_constants (THD *thd, I_List< COND_CMP > *save_list, Item *and_father, Item *cond) |
Propagate constant values in a condition. More... | |
uint | build_bitmap_for_nested_joins (mem_root_deque< Table_ref * > *join_list, uint first_unused) |
Assign each nested join structure a bit in nested_join_map. More... | |
double | find_worst_seeks (const TABLE *table, double num_rows, double table_scan_cost) |
Find an artificial cap for ref access. More... | |
static void | semijoin_types_allow_materialization (Table_ref *sj_nest) |
Check if semijoin's compared types allow materialization. More... | |
static bool | check_skip_records_in_range_qualification (JOIN_TAB *tab, THD *thd) |
Index dive can be skipped if the following conditions are satisfied: F1) For a single table query: a) FORCE INDEX applies to a single index. More... | |
uint | get_tmp_table_rec_length (const mem_root_deque< Item * > &items, bool include_hidden, bool can_skip_aggs) |
static bool | add_not_null_conds (JOIN *join) |
Add to join_tab[i]->condition() "table.field IS NOT NULL" conditions we've inferred from ref/eq_ref access performed. More... | |
bool | uses_index_fields_only (Item *item, TABLE *tbl, uint keyno, bool other_tbls_ok) |
Check if given expression only uses fields covered by index keyno in the table tbl. More... | |
static bool | find_eq_ref_candidate (Table_ref *tl, table_map sj_inner_tables) |
static Key_field * | merge_key_fields (Key_field *start, Key_field *new_fields, Key_field *end, uint and_level) |
Merge new key definitions to old ones, remove those not used in both. More... | |
static uint | get_semi_join_select_list_index (Item_field *item_field) |
Given a field, return its index in semi-join's select list, or UINT_MAX. More... | |
static void | warn_index_not_applicable (THD *thd, const Field *field, const Key_map cant_use_index) |
If EXPLAIN or if the –safe-updates option is enabled, add a warning that an index cannot be used for ref access. More... | |
static bool | add_key_field (THD *thd, Key_field **key_fields, uint and_level, Item_func *cond, Item_field *item_field, bool eq_func, Item **value, uint num_values, table_map usable_tables, SARGABLE_PARAM **sargables) |
Add a possible key to array of possible keys if it's usable as a key. More... | |
static bool | add_key_equal_fields (THD *thd, Key_field **key_fields, uint and_level, Item_func *cond, Item_field *field_item, bool eq_func, Item **val, uint num_values, table_map usable_tables, SARGABLE_PARAM **sargables) |
Add possible keys to array of possible keys originated from a simple predicate. More... | |
static bool | is_local_field (Item *field) |
Check if an expression is a non-outer field. More... | |
static bool | is_row_of_local_columns (Item_row *item_row) |
Check if a row constructor expression is over columns in the same query block. More... | |
bool | add_key_fields (THD *thd, JOIN *join, Key_field **key_fields, uint *and_level, Item *cond, table_map usable_tables, SARGABLE_PARAM **sargables) |
The guts of the ref optimizer. More... | |
static bool | add_key_part (Key_use_array *keyuse_array, Key_field *key_field) |
static bool | add_ft_keys (Key_use_array *keyuse_array, Item *cond, table_map usable_tables, bool simple_match_expr) |
Function parses WHERE condition and add key_use for FT index into key_use array if suitable MATCH function is found. More... | |
static bool | sort_keyuse (const Key_use &a, const Key_use &b) |
Compares two keyuse elements. More... | |
static bool | add_key_fields_for_nj (THD *thd, JOIN *join, Table_ref *nested_join_table, Key_field **end, uint *and_level, SARGABLE_PARAM **sargables) |
static store_key * | get_store_key (THD *thd, Item *val, table_map used_tables, table_map const_tables, const KEY_PART_INFO *key_part, uchar *key_buff, uint maybe_null) |
bool | is_show_cmd_using_system_view (THD *thd) |
Check whether the statement is a SHOW command using INFORMATION_SCHEMA system views. More... | |
static ulong | get_max_execution_time (THD *thd) |
Get the maximum execution time for a statement. More... | |
static bool | is_timer_applicable_to_statement (THD *thd) |
Check whether max statement time is applicable to statement or not. More... | |
bool | set_statement_timer (THD *thd) |
Set the time until the currently running statement is aborted. More... | |
void | reset_statement_timer (THD *thd) |
Deactivate the timer associated with the statement that was executed. More... | |
bool | reads_not_secondary_columns (const LEX *lex) |
Checks if a query reads a column that is not available in the secondary engine (i.e. More... | |
static bool | equal_engines (const LEX_CSTRING &engine1, const LEX_CSTRING &engine2) |
const MYSQL_LEX_CSTRING * | get_eligible_secondary_engine_from (const LEX *lex) |
const handlerton * | get_secondary_engine_handlerton (const LEX *lex) |
Returns secondary_engine handler for the statement. More... | |
std::string_view | get_secondary_engine_fail_reason (const LEX *lex) |
std::string_view | find_secondary_engine_fail_reason (const LEX *lex) |
static bool | set_secondary_engine_fail_reason (const LEX *lex, std::string_view reason) |
void | set_fail_reason_and_raise_error (const LEX *lex, std::string_view reason) |
void | find_and_set_offload_fail_reason (const LEX *lex) |
bool | validate_use_secondary_engine (const LEX *lex) |
Validates a query that uses the secondary engine. More... | |
bool | optimize_secondary_engine (THD *thd) |
Perform query optimizations that are specific to a secondary storage engine. More... | |
void | notify_plugins_after_select (THD *thd, const Sql_cmd *cmd) |
Notify plugins about an executed SELECT statement. More... | |
static bool | check_locking_clause_access (THD *thd, Global_tables_list tables) |
Performs access check for the locking clause, if present. More... | |
bool | types_allow_materialization (Item *outer, Item *inner) |
Check if two items are compatible wrt. More... | |
static bool | sj_table_is_included (JOIN *join, JOIN_TAB *join_tab) |
SJ_TMP_TABLE * | create_sj_tmp_table (THD *thd, JOIN *join, SJ_TMP_TABLE_TAB *first_tab, SJ_TMP_TABLE_TAB *last_tab) |
Set up the support structures (NULL bits, row offsets, etc.) for a semijoin duplicate weedout table. More... | |
static bool | setup_semijoin_dups_elimination (JOIN *join, uint no_jbuf_after) |
Setup the strategies to eliminate semi-join duplicates. More... | |
static void | destroy_sj_tmp_tables (JOIN *join) |
bool | check_privileges_for_join (THD *thd, mem_root_deque< Table_ref * > *tables) |
Check privileges for column references in a JOIN expression. More... | |
bool | check_privileges_for_list (THD *thd, const mem_root_deque< Item * > &items, Access_bitmask privileges) |
Check privileges for column references in an item list. More... | |
void | calc_used_field_length (TABLE *table, bool needs_rowid, uint *p_used_fieldlength) |
Find how much space the previous read not const tables takes in cache. More... | |
void | calc_length_and_keyparts (Key_use *keyuse, JOIN_TAB *tab, const uint key, table_map used_tables, Key_use **chosen_keyuses, uint *length_out, uint *keyparts_out, table_map *dep_map, bool *maybe_null) |
Calculate properties of ref key: key length, number of used key parts, dependency map, possibility of null. More... | |
bool | init_ref (THD *thd, unsigned keyparts, unsigned length, unsigned keyno, Index_lookup *ref) |
Initialize the given TABLE_REF; setting basic fields and allocating memory for arrays. More... | |
bool | init_ref_part (THD *thd, unsigned part_no, Item *val, bool *cond_guard, bool null_rejecting, table_map const_tables, table_map used_tables, bool nullable, const KEY_PART_INFO *key_part_info, uchar *key_buff, Index_lookup *ref) |
Initialize a given keypart in the table ref. More... | |
bool | create_ref_for_key (JOIN *join, JOIN_TAB *j, Key_use *org_keyuse, table_map used_tables) |
Setup a ref access for looking up rows via an index (a key). More... | |
static store_key::store_key_result | type_conversion_status_to_store_key (THD *thd, type_conversion_status ts) |
bool | and_conditions (Item **e1, Item *e2) |
Extend e1 by AND'ing e2 to the condition e1 points to. More... | |
static Item * | make_cond_for_index (Item *cond, TABLE *table, uint keyno, bool other_tbls_ok) |
static Item * | make_cond_remainder (Item *cond, bool exclude_index) |
bool | make_join_readinfo (JOIN *join, uint no_jbuf_after) |
Plan refinement stage: do various setup things for the executor. More... | |
static void | cleanup_table (TABLE *table) |
ORDER * | simple_remove_const (ORDER *order, Item *where) |
Filter out ORDER BY items that are equal to constants in WHERE condition. More... | |
bool | equality_determines_uniqueness (const Item_func_comparison *func, const Item *v, const Item *c) |
Check if equality can be used to remove sub-clause of GROUP BY/ORDER BY. More... | |
bool | equality_has_no_implicit_casts (const Item_func_comparison *func, const Item *item1, const Item *item2) |
Check whether equality between two items is exact, ie., there are no implicit casts involved. More... | |
static bool | equal (const Item *i1, const Item *i2, const Field *f2) |
bool | check_field_is_const (Item *cond, const Item *order_item, const Field *order_field, Item **const_item) |
Check if a field is equal to a constant value in a condition. More... | |
void | count_field_types (const Query_block *query_block, Temp_table_param *param, const mem_root_deque< Item * > &fields, bool reset_with_sum_func, bool save_sum_fields) |
Update TMP_TABLE_PARAM with count of the different type of fields. More... | |
bool | test_if_subpart (ORDER *a, ORDER *b) |
Return 1 if second is a subpart of first argument. More... | |
void | calc_group_buffer (JOIN *join, ORDER *group, Temp_table_param *tmp_table_param) |
calc how big buffer we need for comparing group entries. More... | |
void | free_underlaid_joins (Query_block *select) |
Free joins of subselect of this select. More... | |
bool | CreateFramebufferTable (THD *thd, const Temp_table_param &tmp_table_param, const Query_block &query_block, const mem_root_deque< Item * > &source_fields, const mem_root_deque< Item * > &window_output_fields, Func_ptr_array *mapping_from_source_to_window_output, Window *window) |
bool | test_if_cheaper_ordering (const JOIN_TAB *tab, ORDER_with_src *order, TABLE *table, Key_map usable_keys, int ref_key, ha_rows select_limit, int *new_key, int *new_key_direction, ha_rows *new_select_limit, uint *new_used_key_parts, uint *saved_best_key_parts, double *new_read_time) |
Find a cheaper access key than a given key. More... | |
uint | get_index_for_order (ORDER_with_src *order, TABLE *table, ha_rows limit, AccessPath *range_scan, bool *need_sort, bool *reverse) |
Find a key to apply single table UPDATE/DELETE by a given ORDER. More... | |
uint | actual_key_parts (const KEY *key_info) |
Returns number of key parts depending on OPTIMIZER_SWITCH_USE_INDEX_EXTENSIONS flag. More... | |
uint | actual_key_flags (const KEY *key_info) |
Returns key flags depending on OPTIMIZER_SWITCH_USE_INDEX_EXTENSIONS flag. More... | |
join_type | calc_join_type (AccessPath *path) |
JOIN::JOIN (THD *thd_arg, Query_block *select) | |
bool | JOIN::alloc_ref_item_slice (THD *thd_arg, int sliceno) |
Allocate a ref_item slice, assume that slice size is in ref_items[0]. More... | |
bool | JOIN::alloc_indirection_slices () |
bool | JOIN::check_access_path_with_fts () const |
Checks if the chosen plan suffers from a problem related to full-text search and streaming aggregation, which is likely to cause wrong results or make the query misbehave in other ways, and raises an error if so. More... | |
bool | JOIN::optimize (bool finalize_access_paths) |
Optimizes one query block into a query execution plan (QEP.) More... | |
void | JOIN::change_to_access_path_without_in2exists () |
If this query block was planned twice, once with and once without conditions added by in2exists, changes the root access path to the one without in2exists. More... | |
AccessPath * | JOIN::create_access_paths_for_zero_rows () const |
Create access paths with the knowledge that there are going to be zero rows coming from tables (before aggregation); typically because we know that all of them would be filtered away by WHERE (e.g. More... | |
bool | JOIN::push_to_engines () |
Handle offloading of query parts to the underlying engines, when such is supported by their implementation. More... | |
void | JOIN::set_plan_state (enum_plan_state plan_state_arg) |
Sets the plan's state of the JOIN. More... | |
bool | JOIN::alloc_qep (uint n) |
void | QEP_TAB::init (JOIN_TAB *jt) |
Initializes the object from a JOIN_TAB. More... | |
uint | QEP_TAB::get_sj_strategy () const |
uint | QEP_TAB::effective_index () const |
Return the index used for a table in a QEP. More... | |
uint | JOIN_TAB::get_sj_strategy () const |
int | JOIN::replace_index_subquery () |
Check whether this is a subquery that can be evaluated by index look-ups. More... | |
bool | JOIN::optimize_distinct_group_order () |
Optimize DISTINCT, GROUP BY, ORDER BY clauses. More... | |
void | JOIN::test_skip_sort () |
Test if an index could be used to replace filesort for ORDER BY/GROUP BY. More... | |
bool | JOIN::prune_table_partitions () |
Prune partitions for all tables of a join (query block). More... | |
void | JOIN::adjust_access_methods () |
An utility function - apply heuristics and optimize access methods to tables. More... | |
bool | JOIN::get_best_combination () |
Set up JOIN_TAB structs according to the picked join order in best_positions. More... | |
table_map | JOIN::calculate_deps_of_remaining_lateral_derived_tables (table_map plan_tables, uint idx) const |
Finds the dependencies of the remaining lateral derived tables. More... | |
void | JOIN::update_depend_map () |
Update the dependency map for the tables. More... | |
void | JOIN::update_depend_map (ORDER *order) |
Update the dependency map for the sort order. More... | |
bool | JOIN::update_equalities_for_sjm () |
Update equalities and keyuse references after semi-join materialization strategy is chosen. More... | |
void | JOIN::set_prefix_tables () |
Assign set of available (prefix) tables to all tables in query block. More... | |
bool | JOIN::make_join_plan () |
Calculate best possible join order and initialize the join structure. More... | |
bool | JOIN::init_planner_arrays () |
Initialize scratch arrays for the join order optimization. More... | |
bool | JOIN::propagate_dependencies () |
Propagate dependencies between tables due to outer join relations. More... | |
bool | JOIN::extract_const_tables () |
Extract const tables based on row counts. More... | |
bool | JOIN::extract_func_dependent_tables () |
Extract const tables based on functional dependencies. More... | |
void | JOIN::update_sargable_from_const (SARGABLE_PARAM *sargables) |
Update info on indexes that can be used for search lookups as reading const tables may has added new sargable predicates. More... | |
bool | JOIN::estimate_rowcount () |
Estimate the number of matched rows for each joined table. More... | |
void | JOIN::set_semijoin_embedding () |
Set semi-join embedding join nest pointers. More... | |
bool | Sql_cmd_dml::prepare (THD *thd) override |
Command-specific resolving (doesn't include LEX::prepare()) More... | |
bool | Sql_cmd_select::accept (THD *thd, Select_lex_visitor *visitor) override |
const MYSQL_LEX_CSTRING * | Sql_cmd_select::eligible_secondary_storage_engine (THD *thd) const override |
Is this statement of a type and on a form that makes it eligible for execution in a secondary storage engine? More... | |
bool | Sql_cmd_select::prepare_inner (THD *thd) override |
Prepare a SELECT statement. More... | |
bool | Sql_cmd_dml::execute (THD *thd) override |
Execute a DML statement. More... | |
virtual bool | Sql_cmd_dml::execute_inner (THD *thd) |
The inner parts of query optimization and execution. More... | |
virtual bool | Sql_cmd_dml::restore_cmd_properties (THD *thd) |
Restore command properties before execution. More... | |
virtual bool | Sql_cmd_dml::save_cmd_properties (THD *thd) |
Save command properties, such as prepared query details and table props. More... | |
Query_result * | Sql_cmd_dml::query_result () const |
void | Sql_cmd_dml::set_query_result (Query_result *result) |
Set query result object for this query statement. More... | |
bool | Sql_cmd_select::precheck (THD *thd) override |
Perform an authorization precheck for an unprepared SELECT statement. More... | |
bool | Sql_cmd_select::check_privileges (THD *thd) override |
Perform an authorization check for a prepared SELECT statement. More... | |
bool | Sql_cmd_dml::check_all_table_privileges (THD *thd) |
Read and check privileges for all tables in a DML statement. More... | |
const MYSQL_LEX_CSTRING * | Sql_cmd_dml::get_eligible_secondary_engine (THD *thd) const |
Helper function that checks if the command is eligible for secondary engine and if that's true returns the name of that eligible secondary storage engine. More... | |
bool | JOIN::clear_sj_tmp_tables () |
Remove all rows from all temp tables used by NL-semijoin runtime. More... | |
bool | JOIN::clear_corr_derived_tmp_tables () |
Empties all correlated materialized derived tables. More... | |
void | JOIN::reset () |
Reset the state of this join object so that it is ready for a new execution. More... | |
bool | JOIN::prepare_result () |
Prepare join result. More... | |
void | JOIN::destroy () |
Clean up and destroy join object. More... | |
void | JOIN::cleanup_item_list (const mem_root_deque< Item * > &items) const |
bool | Query_block::optimize (THD *thd, bool finalize_access_paths) |
Optimize a query block and all inner query expressions. More... | |
bool | Query_block::check_column_privileges (THD *thd) |
Check privileges for all columns referenced from query block. More... | |
bool | Query_block::check_privileges_for_subqueries (THD *thd) |
Check privileges for column references in subqueries of a query block. More... | |
bool | JOIN::init_ref_access () |
Initialize ref access for all tables that use it. More... | |
void | JOIN::set_semijoin_info () |
Set the first_sj_inner_tab and last_sj_inner_tab fields for all tables inside the semijoin nests of the query. More... | |
store_key::store_key (THD *thd, Field *to_field_arg, uchar *ptr, uchar *null_ptr_arg, uint length, Item *item_arg) | |
store_key_result | store_key::copy () |
sets ignore truncation warnings mode and calls the real copy method More... | |
enum store_key_result | store_key_hash_item::copy_inner () override |
virtual enum store_key_result | store_key::copy_inner () |
void | QEP_TAB::push_index_cond (const JOIN_TAB *join_tab, uint keyno, Opt_trace_object *trace_obj) |
Try to extract and push the index condition down to table handler. More... | |
bool | JOIN::setup_semijoin_materialized_table (JOIN_TAB *tab, uint tableno, POSITION *inner_pos, POSITION *sjm_pos) |
Setup the materialized table for a semi-join nest. More... | |
void | QEP_TAB::init_join_cache (JOIN_TAB *join_tab) |
A helper function that allocates appropriate join cache object and sets next_query_block function of previous tab. More... | |
void | JOIN_TAB::set_table (TABLE *t) |
void | JOIN_TAB::init_join_cond_ref (Table_ref *tl) |
Sets the pointer to the join condition of Table_ref. More... | |
void | JOIN_TAB::cleanup () |
Clean up associated table after query execution, including resources. More... | |
void | QEP_TAB::cleanup () |
void | QEP_shared_owner::qs_cleanup () |
uint | QEP_TAB::sjm_query_block_id () const |
bool | QEP_shared_owner::and_with_condition (Item *tmp_cond) |
Extend join_tab->cond by AND'ing add_cond to it. More... | |
void | JOIN::join_free () |
Release memory and, if possible, the open tables held by this execution plan (and nested plans). More... | |
void | JOIN::cleanup () |
Cleanup this JOIN. More... | |
bool | JOIN::alloc_func_list () |
Make an array of pointers to sum_functions to speed up sum_func calculation. More... | |
bool | JOIN::make_sum_func_list (const mem_root_deque< Item * > &fields, bool before_group_by, bool recompute=false) |
Initialize 'sum_funcs' array with all Item_sum objects. More... | |
bool | Query_block::change_query_result (THD *thd, Query_result_interceptor *new_result, Query_result_interceptor *old_result) |
Change the Query_result object of the query block. More... | |
bool | JOIN::add_having_as_tmp_table_cond (uint curr_tmp_table) |
Add having condition as a filter condition, which is applied when reading from the temp table. More... | |
bool | JOIN::make_tmp_tables_info () |
Init tmp tables usage info. More... | |
void | JOIN::refresh_base_slice () |
In the case of rollup (only): After the base slice list was made, we may have modified the field list to add rollup group items and sum switchers, but there may be Items with refs that refer to the base slice. More... | |
void | JOIN::assign_fields_to_slice (int sliceno) |
Similar to refresh_base_slice(), but refreshes only the specified slice. More... | |
void | JOIN::unplug_join_tabs () |
bool | JOIN::add_sorting_to_table (uint idx, ORDER_with_src *order, bool sort_before_group) |
Add Filesort object to the given table to sort if with filesort. More... | |
Variables | |
const char * | antijoin_null_cond = "<ANTIJOIN-NULL>" |
#define KEY_OPTIMIZE_EXISTS 1 |
#define KEY_OPTIMIZE_REF_OR_NULL 2 |
A list interface over the Table_ref::next_global pointer.
JOIN::JOIN | ( | THD * | thd_arg, |
Query_block * | select | ||
) |
store_key::store_key | ( | THD * | thd, |
Field * | to_field_arg, | ||
uchar * | ptr, | ||
uchar * | null_ptr_arg, | ||
uint | length, | ||
Item * | item_arg | ||
) |
|
overridevirtual |
Reimplemented from Sql_cmd.
uint actual_key_flags | ( | const KEY * | key_info | ) |
Returns key flags depending on OPTIMIZER_SWITCH_USE_INDEX_EXTENSIONS flag.
key_info | pointer to KEY structure |
uint actual_key_parts | ( | const KEY * | key_info | ) |
Returns number of key parts depending on OPTIMIZER_SWITCH_USE_INDEX_EXTENSIONS flag.
key_info | pointer to KEY structure |
|
static |
Function parses WHERE condition and add key_use for FT index into key_use array if suitable MATCH function is found.
Condition should be a set of AND expression, OR is not supported. MATCH function should be a part of simple expression. Simple expression is MATCH only function or MATCH is a part of comparison expression ('>=' or '>' operations are supported). It also sets FT_HINTS values(op_type, op_value).
keyuse_array | Key_use array |
cond | WHERE condition |
usable_tables | usable tables |
simple_match_expr | true if this is the first call false otherwise. if MATCH function is found at first call it means that MATCH is simple expression, otherwise, in case of AND/OR condition this parameter will be false. |
true | if FT key was added to Key_use array |
false | if no key was added to Key_use array |
|
private |
Add having condition as a filter condition, which is applied when reading from the temp table.
curr_tmp_table | Table number to which having conds are added. |
|
static |
Add possible keys to array of possible keys originated from a simple predicate.
thd | session context | |
[in,out] | key_fields | Pointer to add key, if usable is incremented if key was stored in the array |
and_level | And level, to be stored in Key_field | |
cond | Condition predicate | |
field_item | Field used in comparison | |
eq_func | True if we used =, <=> or IS NULL | |
val | Value used for comparison with field Is NULL for BETWEEN and IN | |
num_values | Number of elements in the array of values | |
usable_tables | Tables which can be used for key optimization | |
sargables | IN/OUT Array of found sargable candidates |
|
static |
Add a possible key to array of possible keys if it's usable as a key.
[in,out] | key_fields | Used as an input parameter in the sense that it is a pointer to a pointer to a memory area where an array of Key_field objects will stored. It is used as an out parameter in the sense that the pointer will be updated to point beyond the last Key_field written. |
thd | session context | |
and_level | And level, to be stored in Key_field | |
cond | Condition predicate | |
item_field | Field used in comparison | |
eq_func | True if we used =, <=> or IS NULL | |
value | Array of values used for comparison with field | |
num_values | Number of elements in the array of values | |
usable_tables | Tables which can be used for key optimization | |
sargables | IN/OUT Array of found sargable candidates. Will be ignored in case eq_func is true. |
bool add_key_fields | ( | THD * | thd, |
JOIN * | join, | ||
Key_field ** | key_fields, | ||
uint * | and_level, | ||
Item * | cond, | ||
table_map | usable_tables, | ||
SARGABLE_PARAM ** | sargables | ||
) |
The guts of the ref optimizer.
This function, along with the other add_key_* functions, make up a recursive procedure that analyzes a condition expression (a tree of AND and OR predicates) and does many things.
thd | session context | |
join | The query block involving the condition. | |
[in,out] | key_fields | Start of memory buffer, see below. |
[in,out] | and_level | Current 'and level', see below. |
cond | The conditional expression to analyze. | |
usable_tables | Tables not in this bitmap will not be examined. | |
[in,out] | sargables | End of memory buffer, see below. |
This documentation is the result of reverse engineering and may therefore not capture the full gist of the procedure, but it is known to do the following:
The Key_field objects are marked with something called an 'and_level', which does not correspond to their nesting depth within the expression tree. It is rather a tag to group conjunctions together. For instance, in the conditional expression
two Key_field's are produced, both having an and_level of 0.
In an expression such as
three Key_field's are produced, the first two corresponding to 'a = 0' and 'b = 0', respectively, both with and_level 0. The third one corresponds to 'a = 1' and has an and_level of 1.
A separate function, merge_key_fields() performs ref access validation on the Key_field array on the recursice ascent. If some Key_field's cannot be used for ref access, the key_fields pointer is rolled back. All other modifications to the query plan remain.
|
static |
|
static |
Discover the indexes that might be used for GROUP BY or DISTINCT queries or indexes that might be used for SKIP SCAN.
If the query has a GROUP BY clause, find all indexes that contain all GROUP BY fields, and add those indexes to join_tab->const_keys and join_tab->keys.
If the query has a DISTINCT clause, find all indexes that contain all SELECT fields, and add those indexes to join_tab->const_keys and join_tab->keys. This allows later on such queries to be processed by a GroupIndexSkipScanIterator.
If the query does not have GROUP BY clause or any aggregate function the function collects possible keys to use for skip scan access.
Note that indexes that are not usable for resolving GROUP BY/DISTINCT may also be added in some corner cases. For example, an index covering 'a' and 'b' is not usable for the following query but is still added: "SELECT DISTINCT a+b FROM t1". This is not a big issue because a) although the optimizer will consider using the index, it will not chose it (so minor calculation cost added but not wrong result) and b) it applies only to corner cases.
join | the current join |
join_tab | joined table |
|
static |
Add to join_tab[i]->condition() "table.field IS NOT NULL" conditions we've inferred from ref/eq_ref access performed.
This function is a part of "Early NULL-values filtering for ref access" optimization.
Example of this optimization: For query SELECT * FROM t1,t2 WHERE t2.key=t1.field
and plan " any-access(t1), ref(t2.key=t1.field) "
add "t1.field IS NOT NULL" to t1's table condition.
Description of the optimization:
We look through equalities chosen to perform ref/eq_ref access, pick equalities that have form "tbl.part_of_key = othertbl.field" (where othertbl is a non-const table and othertbl.field may be NULL) and add them to conditions on corresponding tables (othertbl in this example).
Exception from that is the case when referred_tab->join != join. I.e. don't add NOT NULL constraints from any embedded subquery. Consider this query:
Here condition A.f3 IS NOT NULL is going to be added to the WHERE condition of the embedding query. Another example: SELECT * FROM t10, t11 WHERE (t10.a < 10 OR t10.a IS NULL) AND t11.b <=> t10.b AND (t11.a = (SELECT MAX(a) FROM t12 WHERE t12.b = t10.a )); Here condition t10.a IS NOT NULL is going to be added. In both cases addition of NOT NULL condition will erroneously reject some rows of the result set. referred_tab->join != join constraint would disallow such additions.
This optimization doesn't affect the choices that ref, range, or join optimizer make. This was intentional because this was added after 4.1 was GA.
Implementation overview
bool JOIN::add_sorting_to_table | ( | uint | idx, |
ORDER_with_src * | sort_order, | ||
bool | sort_before_group | ||
) |
Add Filesort object to the given table to sort if with filesort.
idx | JOIN_TAB's position in the qep_tab array. The created Filesort object gets attached to this. |
sort_order | List of expressions to sort the table by |
sort_before_group | If true, this sort happens before grouping is done (potentially as a step of grouping itself), so any wrapped rollup group items should be unwrapped. |
|
private |
An utility function - apply heuristics and optimize access methods to tables.
Currently this function can change REF to RANGE and ALL to INDEX scan if latter is considered to be better (not cost-based) than the former.
bool JOIN::alloc_func_list | ( | ) |
Make an array of pointers to sum_functions to speed up sum_func calculation.
0 | ok |
1 | Error |
|
private |
|
private |
bool JOIN::alloc_ref_item_slice | ( | THD * | thd_arg, |
int | sliceno | ||
) |
Allocate a ref_item slice, assume that slice size is in ref_items[0].
thd_arg | thread handler |
sliceno | The slice number to allocate in JOIN::ref_items |
Extend e1 by AND'ing e2 to the condition e1 points to.
The resulting condition is fixed. Requirement: the input Items must already have been fixed. This is a variant of and_items(); it is intended for use in the optimizer phase.
[in,out] | e1 | Pointer to condition that will be extended with e2 |
e2 | Condition that will extend e1 |
true | if there was a memory allocation error, in which case e1 remains unchanged |
false | otherwise |
bool QEP_shared_owner::and_with_condition | ( | Item * | add_cond | ) |
Extend join_tab->cond by AND'ing add_cond to it.
add_cond | The condition to AND with the existing cond for this JOIN_TAB |
true | if there was a memory allocation error |
false | otherwise |
void JOIN::assign_fields_to_slice | ( | int | sliceno | ) |
Similar to refresh_base_slice(), but refreshes only the specified slice.
uint build_bitmap_for_nested_joins | ( | mem_root_deque< Table_ref * > * | join_list, |
uint | first_unused | ||
) |
Assign each nested join structure a bit in nested_join_map.
join_list | List of tables |
first_unused | Number of first unused bit in nested_join_map before the call |
|
static |
Build multiple equalities for a WHERE condition and all join conditions that inherit these multiple equalities.
The function first applies the build_equal_items_for_cond function to build all multiple equalities for condition cond utilizing equalities referred through the parameter inherited. The extended set of equalities is returned in the structure referred by the cond_equal_ref parameter. After this the function calls itself recursively for all join conditions whose direct references can be found in join_list and who inherit directly the multiple equalities just having built.
Interesting that multiple equality =(t1.a,t2.a,t3.a,t4.a) allows us to use t1.a=t3.a AND t3.a=t4.a under the join condition:
This query equivalent to:
Similarly the original query can be rewritten to the query:
that is equivalent to:
Thus, applying equalities from the where condition we basically can get more freedom in performing join operations. Although we don't use this property now, it probably makes sense to use it in the future.
thd | Thread handler | |
cond | condition to build the multiple equalities for | |
[out] | retcond | Returned condition |
inherited | path to all inherited multiple equality items | |
do_inherit | whether or not to inherit equalities from other parts of the condition | |
join_list | list of join tables that the condition refers to | |
[out] | cond_equal_ref | pointer to the structure to place built equalities in |
|
static |
Replace all equality predicates in a condition by multiple equality items.
At each 'and' level the function detects items for equality predicates and replaces them by a set of multiple equality items of class Item_multi_eq, taking into account inherited equalities from upper levels. If an equality predicate is used not in a conjunction it's just replaced by a multiple equality predicate. For each 'and' level the function set a pointer to the inherited multiple equalities in the cond_equal field of the associated object of the type Item_cond_and. The function also traverses the cond tree and for each field reference sets a pointer to the multiple equality item containing the field, if there is any. If this multiple equality equates fields to a constant the function replaces the field reference by the constant in the cases when the field is not of a string type or when the field reference is just an argument of a comparison predicate. The function also determines the maximum number of members in equality lists of each Item_cond_and object assigning it to thd->lex->current_query_block()->max_equal_elems.
The function performs the substitution in a recursive descent of the condition tree, passing to the next AND level a chain of multiple equality predicates which have been built at the upper levels. The Item_multi_eq items built at the level are attached to other non-equality conjuncts as a sublist. The pointer to the inherited multiple equalities is saved in the and condition object (Item_cond_and). This chain allows us for any field reference occurrence to easily find a multiple equality that must be held for this occurrence. For each AND level we do the following:
We need to do things in this order as lower AND levels need to know about all possible Item_multi_eq objects in upper levels.
thd | thread handle | |
cond | condition(expression) where to make replacement | |
[out] | retcond | returned condition |
inherited | path to all inherited multiple equality items | |
do_inherit | whether or not to inherit equalities from other parts of the condition |
void calc_group_buffer | ( | JOIN * | join, |
ORDER * | group, | ||
Temp_table_param * | tmp_table_param | ||
) |
calc how big buffer we need for comparing group entries.
join_type calc_join_type | ( | AccessPath * | path | ) |
void calc_length_and_keyparts | ( | Key_use * | keyuse, |
JOIN_TAB * | tab, | ||
const uint | key, | ||
table_map | used_tables, | ||
Key_use ** | chosen_keyuses, | ||
uint * | length_out, | ||
uint * | keyparts_out, | ||
table_map * | dep_map, | ||
bool * | maybe_null | ||
) |
Calculate properties of ref key: key length, number of used key parts, dependency map, possibility of null.
After calling this function thd::is_error() needs to be checked, as it can set an error.
keyuse | Array of keys to consider | |
tab | join_tab to calculate ref parameters for | |
key | number of the key to use | |
used_tables | tables read prior to this table | |
[out] | chosen_keyuses | when given, this function will fill array with chosen keyuses |
[out] | length_out | calculated length of the ref |
[out] | keyparts_out | calculated number of used keyparts |
[out] | dep_map | when given, calculated dependency map |
[out] | maybe_null | when given, calculated maybe_null property |
void calc_used_field_length | ( | TABLE * | table, |
bool | needs_rowid, | ||
uint * | p_used_fieldlength | ||
) |
Find how much space the previous read not const tables takes in cache.
table_map JOIN::calculate_deps_of_remaining_lateral_derived_tables | ( | table_map | plan_tables, |
uint | idx | ||
) | const |
Finds the dependencies of the remaining lateral derived tables.
plan_tables | map of all tables that the planner is processing (tables already in plan and tables to be added to plan). |
idx | index of the table which the planner is currently considering. |
|
static |
For {semijoin,subquery} materialization: calculates various cost information, based on a plan in join->best_positions covering the to-be-materialized query block and only this.
join | JOIN where plan can be found | |
sj_nest | sj materialization nest (NULL if subquery materialization) | |
n_tables | number of to-be-materialized tables | |
[out] | sjm | where computed costs will be stored |
|
static |
A helper function to check whether it's better to use range than ref.
Heuristic: Switch from 'ref' to 'range' access if 'range' access can utilize more keyparts than 'ref' access. Conditions for doing switching:
1) Range access is possible 2) 'ref' access and 'range' access uses the same index 3) Used parts of key shouldn't have nullable parts & ref_or_null isn't used. 4) 'ref' access depends on a constant, not a value read from a table earlier in the join sequence.
Rationale: if 'ref' depends on a value from another table, the join condition is not used to limit the rows read by 'range' access (that would require dynamic range - 'Range checked for each record'). In other words, if 'ref' depends on a value from another table, we have a query with conditions of the form
this_table.idx_col1 = other_table.col AND <<- used by 'ref' this_table.idx_col1 OP <const> AND <<- used by 'range' this_table.idx_col2 OP <const> AND ... <<- used by 'range'
and an index on (idx_col1,idx_col2,...). But the fact that 'range' access uses more keyparts does not mean that it is more selective than 'ref' access because these access types utilize different parts of the query condition. We therefore trust the cost based choice made by best_access_path() instead of forcing a heuristic choice here. 5) 'range' access uses more keyparts than 'ref' access 6) ORDER BY might make range better than table scan: Check possibility of range scan even if it was previously deemed unviable (for example when table scan was estimated to be cheaper). If yes, range-access should be chosen only for larger key length.
thd | To re-run range optimizer. |
tab | JOIN_TAB to check |
ordering | Used as a parameter to call test_quick_select. |
recheck_range | Check possibility of range scan even if it is currently unviable. |
|
static |
change field = field to field = const for each found field = const in the and_level
thd | Thread handler |
save_list | saved list of COND_CMP |
and_father | father of AND op |
cond | Condition where fields are replaced with constant values |
field | The field that will be substituted |
value | The substitution value |
bool Query_block::change_query_result | ( | THD * | thd, |
Query_result_interceptor * | new_result, | ||
Query_result_interceptor * | old_result | ||
) |
Change the Query_result object of the query block.
If old_result is not used, forward the call to the current Query_result in case it is a wrapper around old_result.
Call prepare() on the new Query_result if we decide to use it.
thd | Thread handle |
new_result | New Query_result object |
old_result | Old Query_result object (NULL to force change) |
false | Success |
true | Error |
void JOIN::change_to_access_path_without_in2exists | ( | ) |
If this query block was planned twice, once with and once without conditions added by in2exists, changes the root access path to the one without in2exists.
If not (ie., there were never any such conditions in the first place), does nothing.
|
private |
Checks if the chosen plan suffers from a problem related to full-text search and streaming aggregation, which is likely to cause wrong results or make the query misbehave in other ways, and raises an error if so.
Only to be called for queries with full-text search and GROUP BY WITH ROLLUP.
If there are calls to MATCH in the SELECT list (including the hidden elements lifted there from other clauses), and they are not inside an aggregate function, the results of the MATCH clause need to be materialized before streaming aggregation is performed. The hypergraph optimizer adds a materialization step before aggregation if needed (see CreateStreamingAggregationPath()), but the old optimizer only does that for implicitly grouped queries. For explicitly grouped queries, it instead disables streaming aggregation for the queries that would need a materialization step to work correctly (see JOIN::test_skip_sort()).
For explicitly grouped queries WITH ROLLUP, however, streaming aggregation is currently the only alternative. In many cases it still works correctly because an intermediate materialization step has been added for some other reason, typically for a sort. For now, in those cases where a materialization step has not been added, we raise an error instead of going ahead with an invalid execution plan.
|
protected |
Read and check privileges for all tables in a DML statement.
thd | thread handler |
bool Query_block::check_column_privileges | ( | THD * | thd | ) |
Check privileges for all columns referenced from query block.
Check privileges for all columns referenced from this query block.
Also check privileges for referenced subqueries.
thd | thread handler |
|
static |
Eliminate row equalities and form multiple equalities predicates.
This function checks whether the item is a simple equality i.e. the one that equates a field with another field or a constant (field=field_item or field=constant_item), or, a row equality. For a simple equality the function looks for a multiple equality in the lists referenced directly or indirectly by cond_equal inferring the given simple equality. If it doesn't find any, it builds/expands multiple equality that covers the predicate. Row equalities are eliminated substituted for conjunctive regular equalities which are treated in the same way as original equality predicates.
thd | thread handle | |
item | predicate to process | |
cond_equal | multiple equalities that must hold together with the predicate | |
eq_list | results of conversions of row equalities that are not simple enough to form multiple equalities | |
[out] | equality | true if re-writing rules have been applied false otherwise, i.e. if the predicate is not an equality, or if the equality is neither a simple nor a row equality |
bool check_field_is_const | ( | Item * | cond, |
const Item * | order_item, | ||
const Field * | order_field, | ||
Item ** | const_item | ||
) |
Check if a field is equal to a constant value in a condition.
cond | condition to search within | |
order_item | Item to find in condition (if order_field is NULL) | |
order_field | Field to find in condition (if order_item is NULL) | |
[out] | const_item | Used in calculation with conjunctive predicates, must be NULL in outer-most call. |
|
static |
Performs access check for the locking clause, if present.
thd | Current session, used for checking access and raising error. |
tables | Tables in the query's from clause. |
true | There was a locking clause and access was denied. An error has been raised. |
false | There was no locking clause or access was allowed to it. This is always returned in an embedded build. |
|
overrideprotectedvirtual |
Perform an authorization check for a prepared SELECT statement.
Implements Sql_cmd_dml.
Reimplemented in Sql_cmd_show, Sql_cmd_show_schema_base, Sql_cmd_show_table_base, Sql_cmd_show_routine_code, Sql_cmd_show_binlog_events, Sql_cmd_show_binlogs, Sql_cmd_show_create_database, Sql_cmd_show_create_event, Sql_cmd_show_create_function, Sql_cmd_show_create_procedure, Sql_cmd_show_create_table, Sql_cmd_show_create_trigger, Sql_cmd_show_create_user, Sql_cmd_show_databases, Sql_cmd_show_engine_logs, Sql_cmd_show_engine_mutex, Sql_cmd_show_engine_status, Sql_cmd_show_events, Sql_cmd_show_grants, Sql_cmd_show_binary_log_status, Sql_cmd_show_processlist, Sql_cmd_show_relaylog_events, Sql_cmd_show_replicas, and Sql_cmd_show_replica_status.
bool check_privileges_for_join | ( | THD * | thd, |
mem_root_deque< Table_ref * > * | tables | ||
) |
Check privileges for column references in a JOIN expression.
Check privileges for all columns referenced from join expression.
thd | thread handler |
tables | list of joined tables |
bool check_privileges_for_list | ( | THD * | thd, |
const mem_root_deque< Item * > & | items, | ||
Access_bitmask | privileges | ||
) |
Check privileges for column references in an item list.
Check privileges for all columns referenced from an expression list.
thd | thread handler |
items | list of items |
privileges | the required privileges |
bool Query_block::check_privileges_for_subqueries | ( | THD * | thd | ) |
Check privileges for column references in subqueries of a query block.
thd | thread handler |
|
static |
Convert row equalities into a conjunction of regular equalities.
The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n) into a list of equalities E1=E'1,...,En=E'n. For each of these equalities Ei=E'i the function checks whether it is a simple equality or a row equality. If it is a simple equality it is used to expand multiple equalities of cond_equal. If it is a row equality it converted to a sequence of equalities between row elements. If Ei=E'i is neither a simple equality nor a row equality the item for this predicate is added to eq_list.
thd | thread handle | |
left_row | left term of the row equality to be processed | |
right_row | right term of the row equality to be processed | |
cond_equal | multiple equalities that must hold together with the predicate | |
eq_list | results of conversions of row equalities that are not simple enough to form multiple equalities | |
[out] | simple_equality | true if the row equality is composed of only simple equalities. |
|
static |
Check whether an equality can be used to build multiple equalities.
This function first checks whether the equality (left_item=right_item) is a simple equality i.e. one that equates a field with another field or a constant (field=field_item or field=const_item). If this is the case the function looks for a multiple equality in the lists referenced directly or indirectly by cond_equal inferring the given simple equality. If it doesn't find any, it builds a multiple equality that covers the predicate, i.e. the predicate can be inferred from this multiple equality. The built multiple equality could be obtained in such a way: create a binary multiple equality equivalent to the predicate, then merge it, if possible, with one of old multiple equalities. This guarantees that the set of multiple equalities covering equality predicates will be minimal.
EXAMPLE: For the where condition
the check_equality will be called for the following equality predicates a=b, b=c, b=2 and f=e.
The implementation does not follow exactly the above rules to build a new multiple equality for the equality predicate. If it processes the equality of the form field1=field2, it looks for multiple equalities me1 containing field1 and me2 containing field2. If only one of them is found the function expands it with the lacking field. If multiple equalities for both fields are found they are merged. If both searches fail a new multiple equality containing just field1 and field2 is added to the existing multiple equalities. If the function processes the predicate of the form field1=const, it looks for a multiple equality containing field1. If found, the function checks the constant of the multiple equality. If the value is unknown, it is setup to const. Otherwise the value is compared with const and the evaluation of the equality predicate is performed. When expanding/merging equality predicates from the upper levels the function first copies them for the current level. It looks acceptable, as this happens rarely. The implementation without copying would be much more complicated.
thd | Thread handler | |
left_item | left term of the equality to be checked | |
right_item | right term of the equality to be checked | |
item | equality item if the equality originates from a condition predicate, 0 if the equality is the result of row elimination | |
cond_equal | multiple equalities that must hold together with the equality | |
[out] | simple_equality | true if the predicate is a simple equality predicate to be used for building multiple equalities false otherwise |
Index dive can be skipped if the following conditions are satisfied: F1) For a single table query: a) FORCE INDEX applies to a single index.
b) No subquery is present. c) Fulltext Index is not involved. d) No GROUP-BY or DISTINCT clause. e.I) No ORDER-BY clause or e.II) The given index can provide the order.
F2) Not applicable to multi-table query.
tab | JOIN_TAB object. |
thd | THD object. |
void QEP_TAB::cleanup | ( | void | ) |
void JOIN::cleanup | ( | void | ) |
Cleanup this JOIN.
Free resources of given join.
Not a full cleanup. reusable?
void JOIN_TAB::cleanup | ( | void | ) |
Clean up associated table after query execution, including resources.
Cleanup table of join operation.
|
private |
|
static |
bool JOIN::clear_corr_derived_tmp_tables | ( | ) |
Empties all correlated materialized derived tables.
bool JOIN::clear_sj_tmp_tables | ( | ) |
Remove all rows from all temp tables used by NL-semijoin runtime.
All rows must be removed from all temporary tables before every join re-execution.
|
static |
Compare field items by table order in the execution plan.
field1 considered as better than field2 if the table containing field1 is accessed earlier than the table containing field2. The function finds out what of two fields is better according this criteria.
field1 | first field item to compare |
field2 | second field item to compare |
table_join_idx | index to tables determining table order |
-1 | if field1 is better than field2 |
1 | if field2 is better than field1 |
0 | otherwise |
store_key::store_key_result store_key::copy | ( | ) |
sets ignore truncation warnings mode and calls the real copy method
this function makes sure truncation warnings when preparing the key buffers don't end up as errors (because of an enclosing INSERT/UPDATE).
|
protectedvirtual |
|
overrideprotectedvirtual |
Reimplemented from store_key.
void count_field_types | ( | const Query_block * | query_block, |
Temp_table_param * | param, | ||
const mem_root_deque< Item * > & | fields, | ||
bool | reset_with_sum_func, | ||
bool | save_sum_fields | ||
) |
Update TMP_TABLE_PARAM with count of the different type of fields.
This function counts the number of fields, functions and sum functions (items with type SUM_FUNC_ITEM) for use by create_tmp_table() and stores it in the Temp_table_param object. It also updates the allow_group_via_temp_table property if needed.
query_block | Query_block of query |
param | Description of temp table |
fields | List of fields to count |
reset_with_sum_func | Whether to reset with_sum_func of func items |
save_sum_fields | Count in the way create_tmp_table() expects when given the same parameter. |
AccessPath * JOIN::create_access_paths_for_zero_rows | ( | ) | const |
Create access paths with the knowledge that there are going to be zero rows coming from tables (before aggregation); typically because we know that all of them would be filtered away by WHERE (e.g.
SELECT * FROM t1 WHERE 1=2). This will normally yield no output rows, but if we have implicit aggregation, it might yield a single one.
Setup a ref access for looking up rows via an index (a key).
join | The join object being handled |
j | The join_tab which will have the ref access populated |
org_keyuse | First key part of (possibly multi-part) key |
used_tables | Bitmap of available tables |
Given a Key_use structure that specifies the fields that can be used for index access, this function creates and set up the structure used for index look up via one of the access methods {JT_FT, JT_CONST, JT_REF_OR_NULL, JT_REF, JT_EQ_REF} for the plan operator 'j'. Generally the function sets up the structure j->ref (of type Index_lookup), and the access method j->type.
SJ_TMP_TABLE * create_sj_tmp_table | ( | THD * | thd, |
JOIN * | join, | ||
SJ_TMP_TABLE_TAB * | first_tab, | ||
SJ_TMP_TABLE_TAB * | last_tab | ||
) |
Set up the support structures (NULL bits, row offsets, etc.) for a semijoin duplicate weedout table.
The object is allocated on the given THD's MEM_ROOT.
thd | the THD to allocate the object on |
join | the JOIN that will own the temporary table (ie., has the responsibility to destroy it after use) |
first_tab | first table in row key (inclusive) |
last_tab | last table in row key (exclusive) |
bool CreateFramebufferTable | ( | THD * | thd, |
const Temp_table_param & | tmp_table_param, | ||
const Query_block & | query_block, | ||
const mem_root_deque< Item * > & | source_fields, | ||
const mem_root_deque< Item * > & | window_output_fields, | ||
Func_ptr_array * | mapping_from_source_to_window_output, | ||
Window * | window | ||
) |
void JOIN::destroy | ( | ) |
Clean up and destroy join object.
|
static |
uint QEP_TAB::effective_index | ( | ) | const |
Return the index used for a table in a QEP.
The various access methods have different places where the index/key number is stored, so this function is needed to return the correct value.
JT_SYSTEM and JT_ALL does not use an index, and will always return MAX_KEY.
JT_INDEX_MERGE supports more than one index. Hence MAX_KEY is returned and a further inspection is needed.
|
overridevirtual |
Is this statement of a type and on a form that makes it eligible for execution in a secondary storage engine?
Reimplemented from Sql_cmd.
|
static |
Generate minimal set of simple equalities equivalent to a multiple equality.
The function retrieves the fields of the multiple equality item item_equal and for each field f:
thd | the session context |
cond | condition to add the generated equality to |
upper_levels | structure to access multiple equality of upper levels |
item_equal | multiple equality to generate simple equality from |
|
static |
bool equality_determines_uniqueness | ( | const Item_func_comparison * | func, |
const Item * | v, | ||
const Item * | c | ||
) |
Check if equality can be used to remove sub-clause of GROUP BY/ORDER BY.
func | comparison operator (= or <=>) |
v | variable comparison operand (validated to be equal to ordering expression) |
c | other comparison operand (likely to be a constant) |
Checks if an equality predicate can be used to remove a GROUP BY/ORDER BY sub-clause when it is known to be true for exactly one distinct value (e.g. "expr" == "const"). Arguments must be of the same type because e.g. "string_field" = "int_const" may match more than one distinct value from the column.
bool equality_has_no_implicit_casts | ( | const Item_func_comparison * | func, |
const Item * | item1, | ||
const Item * | item2 | ||
) |
Check whether equality between two items is exact, ie., there are no implicit casts involved.
This is especially important for GROUP BY/ORDER BY, as it means they can be treated interchangeably. The primary difference between this and equality_determines_uniqueness() is that item2 does not need to be a constant (which makes it stricter in other aspects).
|
private |
Estimate the number of matched rows for each joined table.
Set up range scan for tables that have proper predicates. Eliminate tables that have filter conditions that are always false based on analysis performed in resolver phase or analysis of range scan predicates.
|
overridevirtual |
Execute a DML statement.
thd | thread handler |
Processing a statement goes through 6 phases (parsing is already done)
If the statement is already prepared, this step is skipped.
The queries handled by this function are:
SELECT INSERT ... SELECT INSERT ... VALUES REPLACE ... SELECT REPLACE ... VALUES UPDATE (single-table and multi-table) DELETE (single-table and multi-table) DO
Implements Sql_cmd.
Reimplemented in Sql_cmd_show, Sql_cmd_show_noplan, and Sql_cmd_show_status.
|
protectedvirtual |
The inner parts of query optimization and execution.
Execute a DML statement.
Single-table DML operations needs to reimplement this.
thd | Thread handler |
This is the default implementation for a DML statement and uses a nested-loop join processor per outer-most query block. The implementation is split in two: One for query expressions containing a single query block and one for query expressions containing multiple query blocks combined with UNION.
Reimplemented in Sql_cmd_call, Sql_cmd_delete, Sql_cmd_insert_values, Sql_cmd_show_routine_code, Sql_cmd_show_binlog_events, Sql_cmd_show_binlogs, Sql_cmd_show_create_database, Sql_cmd_show_create_event, Sql_cmd_show_create_function, Sql_cmd_show_create_procedure, Sql_cmd_show_create_table, Sql_cmd_show_create_trigger, Sql_cmd_show_create_user, Sql_cmd_show_engine_logs, Sql_cmd_show_engine_mutex, Sql_cmd_show_engine_status, Sql_cmd_show_errors, Sql_cmd_show_grants, Sql_cmd_show_binary_log_status, Sql_cmd_show_privileges, Sql_cmd_show_processlist, Sql_cmd_show_profiles, Sql_cmd_show_relaylog_events, Sql_cmd_show_replicas, Sql_cmd_show_replica_status, Sql_cmd_show_warnings, and Sql_cmd_update.
|
private |
Extract const tables based on row counts.
This extraction must be done for each execution. Tables containing exactly zero or one rows are marked as const, but notice the additional constraints checked below. Tables that are extracted have their rows read before actual execution starts and are placed in the beginning of the join_tab array. Thus, they do not take part in join order optimization process, which can significantly reduce the optimization time. The data read from these tables can also be regarded as "constant" throughout query execution, hence the column values can be used for additional constant propagation and extraction of const tables based on eq-ref properties.
The tables are given the type JT_SYSTEM.
|
private |
Extract const tables based on functional dependencies.
This extraction must be done for each execution.
Mark as const the tables that
Tables that are extracted have their rows read before actual execution starts and are placed in the beginning of the join_tab array, just as described for JOIN::extract_const_tables().
The tables are given the type JT_CONST.
void find_and_set_offload_fail_reason | ( | const LEX * | lex | ) |
|
static |
Helper function for list_contains_unique_index.
Find a field reference in a dynamic list of Items. Finds a direct reference of the Field in the list.
[in] | field | The field to search for. |
[in] | data | List<Item> *.The list to search in |
1 | found |
0 | not found. |
|
static |
Helper function for list_contains_unique_index.
Find a field reference in a list of ORDER structures. Finds a direct reference of the Field in the list.
field | The field to search for. |
data | ORDER *.The list to search in |
1 | found |
0 | not found. |
Item_multi_eq * find_item_equal | ( | COND_EQUAL * | cond_equal, |
const Item_field * | item_field, | ||
bool * | inherited_fl | ||
) |
Find the multiple equality predicate containing a field.
The function retrieves the multiple equalities accessed through the cond_equal structure from current level and up looking for an equality containing a field. It stops retrieval as soon as the equality is found and set up inherited_fl to true if it's found on upper levels.
cond_equal | multiple equalities to search in | |
item_field | field to look for | |
[out] | inherited_fl | set up to true if multiple equality is found on upper levels (not on current level of cond_equal) |
std::string_view find_secondary_engine_fail_reason | ( | const LEX * | lex | ) |
Find shortest key suitable for full table scan.
table | Table to scan |
usable_keys | Allowed keys |
double find_worst_seeks | ( | const TABLE * | table, |
double | num_rows, | ||
double | table_scan_cost | ||
) |
Find an artificial cap for ref access.
This is mostly a crutch to mitigate that we don't estimate the cache effects of ref accesses properly (ie., normally, if we do many, they will hit cache instead of being separate seeks). Given to find_cost_for_ref().
void free_underlaid_joins | ( | Query_block * | select | ) |
Free joins of subselect of this select.
select | pointer to Query_block which subselects joins we will free |
bool JOIN::get_best_combination | ( | ) |
Set up JOIN_TAB structs according to the picked join order in best_positions.
This allocates execution structures so may be called only after we have the very final plan. It must be called after Optimize_table_order::fix_semijoin_strategies().
Notice that intermediate tables will not have a POSITION reference; and they will not have a TABLE reference before the final stages of code generation.
Item_field * get_best_field | ( | Item_field * | item_field, |
COND_EQUAL * | cond_equal | ||
) |
Get the best field substitution for a given field.
If the field is member of a multiple equality, look up that equality and return the most appropriate field. Usually this is the equivalenced field belonging to the outer-most table in the join order, but
item_field | The field that we are seeking a substitution for. |
cond_equal | multiple equalities to search in |
|
protected |
Helper function that checks if the command is eligible for secondary engine and if that's true returns the name of that eligible secondary storage engine.
const MYSQL_LEX_CSTRING * get_eligible_secondary_engine_from | ( | const LEX * | lex | ) |
uint get_index_for_order | ( | ORDER_with_src * | order, |
TABLE * | table, | ||
ha_rows | limit, | ||
AccessPath * | range_scan, | ||
bool * | need_sort, | ||
bool * | reverse | ||
) |
Find a key to apply single table UPDATE/DELETE by a given ORDER.
order | Linked list of ORDER BY arguments | |
table | Table to find a key | |
limit | LIMIT clause parameter | |
range_scan | Range scan used for this table, if any | |
[out] | need_sort | true if filesort needed |
[out] | reverse | true if the key is reversed again given ORDER (undefined if key == MAX_KEY) |
(end of group Query_Optimizer)
This function is used to get the key length of Item object on which one tmp field will be created during create_tmp_table. This function references KEY_PART_INFO::init_from_field().
item | A inner item of outer join |
|
inlinestatic |
Get the maximum execution time for a statement.
|
static |
Returns estimated number of rows that could be fetched by given access method.
The function calls the range optimizer to estimate the cost of the cheapest QUICK_* index access method to scan one or several of the 'keys' using the conditions 'select->cond'. The range optimizer compares several different types of 'quick select' methods (range scan, index merge, loose index scan) and selects the cheapest one.
If the best index access method is cheaper than a table- and an index scan, then the range optimizer also constructs the corresponding QUICK_* object and assigns it to select->quick. In most cases this is the QUICK_* object used at later (optimization and execution) phases.
thd | Session that runs the query. |
tab | JOIN_TAB of source table. |
limit | maximum number of rows to select. |
condition | the condition to be used for the range check, |
HA_POS_ERROR | For derived tables/views or if an error occur. |
0 | If impossible query (i.e. certainly no rows will be selected.) |
std::string_view get_secondary_engine_fail_reason | ( | const LEX * | lex | ) |
const handlerton * get_secondary_engine_handlerton | ( | const LEX * | lex | ) |
Returns secondary_engine handler for the statement.
If none exist, nullptr is returned.
lex | the statement |
|
static |
Given a field, return its index in semi-join's select list, or UINT_MAX.
item_field | Field to be looked up in select list |
=UINT_MAX | Field is not from a semijoin-transformed subquery |
<UINT_MAX | Index in select list of subquery |
Given a field, find its table; then see if the table is within a semi-join nest and if the field was in select list of the subquery (if subquery was part of a quantified comparison predicate), or the field was a result of subquery decorrelation. If it was, then return the field's index in the select list. The value is used by LooseScan strategy.
uint QEP_TAB::get_sj_strategy | ( | ) | const |
uint JOIN_TAB::get_sj_strategy | ( | ) | const |
Return table number if there is only one table in sort order and group and order is compatible, else return 0.
|
static |
uint get_tmp_table_rec_length | ( | const mem_root_deque< Item * > & | items, |
bool | include_hidden, | ||
bool | can_skip_aggs | ||
) |
|
static |
Check all existing AND'ed predicates in 'cond' for an existing 'is not null 'not_null_item''-predicate.
A condition consisting of multiple AND'ed terms is recursively decomposed in the search for the specified not null predicate.
cond | Condition to be checked. |
not_null_item | The item in: 'is not null 'item'' to search for |
void QEP_TAB::init | ( | JOIN_TAB * | jt | ) |
Initializes the object from a JOIN_TAB.
void QEP_TAB::init_join_cache | ( | JOIN_TAB * | join_tab | ) |
A helper function that allocates appropriate join cache object and sets next_query_block function of previous tab.
A helper function that sets the right op type for join cache (BNL/BKA).
void JOIN_TAB::init_join_cond_ref | ( | Table_ref * | tl | ) |
Sets the pointer to the join condition of Table_ref.
|
private |
Initialize scratch arrays for the join order optimization.
bool init_ref | ( | THD * | thd, |
unsigned | keyparts, | ||
unsigned | length, | ||
unsigned | keyno, | ||
Index_lookup * | ref | ||
) |
Initialize the given TABLE_REF; setting basic fields and allocating memory for arrays.
Call init_ref_part() for each keypart (index field) that is to take part in the ref lookup.
|
private |
Initialize ref access for all tables that use it.
bool init_ref_part | ( | THD * | thd, |
unsigned | part_no, | ||
Item * | val, | ||
bool * | cond_guard, | ||
bool | null_rejecting, | ||
table_map | const_tables, | ||
table_map | used_tables, | ||
bool | nullable, | ||
const KEY_PART_INFO * | key_part_info, | ||
uchar * | key_buff, | ||
Index_lookup * | ref | ||
) |
Initialize a given keypart in the table ref.
In particular, sets up the right function pointer to copy the value from “val” into the ref at execution time (or copies the value right now, if it is constant).
|
static |
Check if an expression is a non-outer field.
Checks if an expression is a field and belongs to the current select.
field | Item expression to check |
true | the expression is a local field |
false | it's something else |
bool is_prefix_index | ( | TABLE * | table, |
uint | idx | ||
) |
Test if this is a prefix index.
table | table |
idx | index to check |
|
static |
Test if REF_OR_NULL optimization will be used if the specified ref_key is used for REF-access to 'tab'.
true | JT_REF_OR_NULL will be used |
false | no JT_REF_OR_NULL access |
|
static |
Check if a row constructor expression is over columns in the same query block.
item_row | Row expression to check. |
true | The expression is a local column reference. |
false | It's something else. |
|
inline |
Check whether the statement is a SHOW command using INFORMATION_SCHEMA system views.
thd | Thread (session) context. |
|
inline |
Test if a second key is the subkey of the first one.
key_part | First key parts |
ref_key_part | Second key parts |
ref_key_part_end | Last+1 part of the second key |
1 | is a subkey |
0 | no sub key |
|
inlinestatic |
Check whether max statement time is applicable to statement or not.
thd | Thread (session) context. |
void JOIN::join_free | ( | ) |
Release memory and, if possible, the open tables held by this execution plan (and nested plans).
Partially cleanup JOIN after it has executed: close index or rnd read (table cursors), free quick selects.
It's used to release some tables before the end of execution in order to increase concurrency and reduce memory consumption.
This function is called in the end of execution of a JOIN, before the used tables are unlocked and closed.
For a join that is resolved using a temporary table, the first sweep is performed against actual tables and an intermediate result is inserted into the temporary table. The last sweep is performed against the temporary table. Therefore, the base tables and associated buffers used to fill the temporary table are no longer needed, and this function is called to free them.
For a join that is performed without a temporary table, this function is called after all rows are sent, but before EOF packet is sent.
For a simple SELECT with no subqueries this function performs a full cleanup of the JOIN and calls mysql_unlock_read_tables to free used base tables.
If a JOIN is executed for a subquery or if it has a subquery, we can't do the full cleanup and need to do a partial cleanup only.
|
static |
Check if GROUP BY/DISTINCT can be optimized away because the set is already known to be distinct.
Used in removing the GROUP BY/DISTINCT of the following types of statements:
If (a,b,c is distinct) then <any combination of a,b,c>,{whatever} is also distinct
This function checks if all the key parts of any of the unique keys of the table are referenced by a list : either the select list through find_field_in_item_list or GROUP BY list through find_field_in_order_list. If the above holds and the key parts cannot contain NULLs then we can safely remove the GROUP BY/DISTINCT, as no result set can be more distinct than an unique key.
tab | The join table to operate on. |
find_func | function to iterate over the list and search for a field |
data | data that's passed through to to find_func |
1 | found |
0 | not found. |
|
static |
|
private |
Calculate best possible join order and initialize the join structure.
The JOIN object is populated with statistics about the query, and a plan with table order and access method selection is made.
The list of tables to be optimized is taken from query_block->leaf_tables. JOIN::where_cond is also used in the optimization. As a side-effect, JOIN::keyuse_array is populated with key_use information.
Here is an overview of the logic of this function:
Separates the predicates in a join condition and pushes them to the join step where all involved tables are available in the join prefix.
ON clauses from JOIN expressions are also pushed to the most appropriate step.
join | Join object where predicates are pushed. |
cond | Pointer to condition which may contain an arbitrary number of predicates, combined using AND, OR and XOR items. If NULL, equivalent to a predicate that returns true for all row combinations. |
true | Found impossible WHERE clause, or out-of-memory |
false | Other |
bool make_join_readinfo | ( | JOIN * | join, |
uint | no_jbuf_after | ||
) |
Plan refinement stage: do various setup things for the executor.
join | Join being processed |
no_jbuf_after | Don't use join buffering after table with this number. |
Plan refinement stage: do various set ups for the executioner
bool JOIN::make_sum_func_list | ( | const mem_root_deque< Item * > & | fields, |
bool | before_group_by, | ||
bool | recompute = false |
||
) |
Initialize 'sum_funcs' array with all Item_sum objects.
fields | All items |
before_group_by | Set to 1 if this is called before GROUP BY handling |
recompute | Set to true if sum_funcs must be recomputed |
0 | ok |
1 | error |
|
private |
Init tmp tables usage info.
This function finalizes execution plan by taking following actions: .) tmp tables are created, but not instantiated (this is done during execution). QEP_TABs dedicated to tmp tables are filled appropriately. see JOIN::create_intermediate_table. .) prepare fields lists (fields, all_fields, ref_item_array slices) for each required stage of execution. These fields lists are set for tmp tables' tabs and for the tab of last table in the join. .) fill info for sorting/grouping/dups removal is prepared and saved to appropriate tabs. Here is an example: SELECT * from t1,t2 WHERE ... GROUP BY t1.f1 ORDER BY t2.f2, t1.f2 and lets assume that the table order in the plan is t1,t2. In this case optimizer will sort for group only the first table as the second one isn't mentioned in GROUP BY. The result will be materialized in tmp table. As filesort can't sort join optimizer will sort tmp table also. The first sorting (for group) is called simple as is doesn't require tmp table. The Filesort object for it is created here - in JOIN::create_intermediate_table. Filesort for the second case is created here, in JOIN::make_tmp_tables_info.
|
static |
Merge new key definitions to old ones, remove those not used in both.
This is called for OR between different levels.
To be able to do 'ref_or_null' we merge a comparison of a column and 'column IS NULL' to one test. This is useful for sub select queries that are internally transformed to something like:.
Key_field::null_rejecting is processed as follows:
result has null_rejecting=true if it is set for both ORed references. for example:
Notify plugins about an executed SELECT statement.
thd | the current session |
cmd | command to be notified about |
|
static |
bool JOIN::optimize | ( | bool | finalize_access_paths | ) |
Optimizes one query block into a query execution plan (QEP.)
This is the entry point to the query optimization phase. This phase applies both logical (equivalent) query rewrites, cost-based join optimization, and rule-based access path selection. Once an optimal plan is found, the member function creates/initializes all structures needed for query execution. The main optimization phases are outlined below:
false | Success. |
true | Error, error code saved in member JOIN::error. |
bool Query_block::optimize | ( | THD * | thd, |
bool | finalize_access_paths | ||
) |
Optimize a query block and all inner query expressions.
thd | thread handler |
finalize_access_paths | if true, finalize access paths, cf. FinalizePlanForQueryBlock |
|
private |
Optimize DISTINCT, GROUP BY, ORDER BY clauses.
false | ok |
true | an error occurred |
bool optimize_secondary_engine | ( | THD * | thd | ) |
Perform query optimizations that are specific to a secondary storage engine.
thd | the current session |
|
static |
Optimize semi-join nests that could be run with sj-materialization.
join | The join to optimize semi-join nests for |
Optimize each of the semi-join nests that can be run with materialization. For each of the nests, we
All obtained information is saved and will be used by the main join optimization pass.
|
overrideprotectedvirtual |
Perform an authorization precheck for an unprepared SELECT statement.
This function will check that we have some privileges to all involved tables of the query (and possibly to other entities).
Implements Sql_cmd_dml.
Reimplemented in Sql_cmd_show.
|
overridevirtual |
Command-specific resolving (doesn't include LEX::prepare())
thd | Current THD. |
Reimplemented from Sql_cmd.
|
overrideprotectedvirtual |
Prepare a SELECT statement.
Implements Sql_cmd_dml.
bool JOIN::prepare_result | ( | ) |
Prepare join result.
Prepare join result prior to join execution or describing. Instantiate derived tables and get schema tables result if necessary.
|
static |
Propagate constant values in a condition.
thd | Thread handler |
save_list | saved list of COND_CMP |
and_father | father of AND op |
cond | Condition for which constant values are propagated |
bool JOIN::propagate_dependencies | ( | ) |
Propagate dependencies between tables due to outer join relations.
Build transitive closure for relation 'to be dependent on'. This will speed up the plan search for many cases with outer joins, as well as allow us to catch illegal cross references. Warshall's algorithm is used to build the transitive closure. As we may restart the outer loop up to 'table_count' times, the complexity of the algorithm is O((number of tables)^3). However, most of the iterations will be shortcircuited when there are no dependencies to propagate.
|
private |
Prune partitions for all tables of a join (query block).
Requires that tables have been locked.
|
static |
Pull tables out of semi-join nests based on functional dependencies.
join | The join where to do the semi-join table pullout |
Pull tables out of semi-join nests based on functional dependencies, ie. if a table is accessed via eq_ref(outer_tables). The function may be called several times, the caller is responsible for setting up proper key information that this function acts upon.
PRECONDITIONS When this function is called, the join may have several semi-join nests but it is guaranteed that one semi-join nest does not contain another. For functionally dependent tables to be pulled out, key information must have been calculated (see update_ref_and_keys()).
POSTCONDITIONS Tables that were pulled out are removed from the semi-join nest they belonged to and added to the parent join nest. For these tables, the used_tables and not_null_tables fields of the semi-join nest they belonged to will be adjusted. The semi-join nest is also marked as correlated, and sj_corr_tables and sj_depends_on are adjusted if necessary. Semi-join nests' sj_inner_tables is set equal to used_tables
NOTE Table pullout may make uncorrelated subquery correlated. Consider this example:
... WHERE oe IN (SELECT it1.primary_key WHERE p(it1, it2) ... )
here table it1 can be pulled out (we have it1.primary_key=oe which gives us functional dependency). Once it1 is pulled out, all references to it1 from p(it1, it2) become references to outside of the subquery and thus make the subquery (i.e. its semi-join nest) correlated. Making the subquery (i.e. its semi-join nest) correlated prevents us from using Materialization or LooseScan to execute it.
void QEP_TAB::push_index_cond | ( | const JOIN_TAB * | join_tab, |
uint | keyno, | ||
Opt_trace_object * | trace_obj | ||
) |
Try to extract and push the index condition down to table handler.
join_tab | join_tab for table |
keyno | Index for which extract and push the condition |
trace_obj | trace object where information is to be added |
bool JOIN::push_to_engines | ( | ) |
Handle offloading of query parts to the underlying engines, when such is supported by their implementation.
Push (parts of) the query execution down to the storage engines if they can provide faster execution of the query, or part of it.
The handler will inspect the QEP through the AQP (Abstract Query Plan) and extract from it whatever it might implement of pushed execution.
It is the responsibility of the handler to store any information it need for the later execution of pushed queries and conditions.
false | Success. |
true | Error, error code saved in member JOIN::error. |
void QEP_shared_owner::qs_cleanup | ( | ) |
Query_result * Sql_cmd_dml::query_result | ( | ) | const |
bool reads_not_secondary_columns | ( | const LEX * | lex | ) |
Checks if a query reads a column that is not available in the secondary engine (i.e.
a column defined with NOT SECONDARY).
lex | Parse tree descriptor. |
void JOIN::refresh_base_slice | ( | ) |
In the case of rollup (only): After the base slice list was made, we may have modified the field list to add rollup group items and sum switchers, but there may be Items with refs that refer to the base slice.
This function refreshes the base slice (and its copy, REF_SLICE_SAVED_BASE) with a fresh copy of the list from “fields”.
When we get rid of slices entirely, we can get rid of this, too.
|
private |
Check whether this is a subquery that can be evaluated by index look-ups.
If so, change subquery engine to subselect_indexsubquery_engine.
1 | engine was changed |
0 | engine wasn't changed |
-1 | OOM or other error |
void JOIN::reset | ( | void | ) |
Reset the state of this join object so that it is ready for a new execution.
void reset_statement_timer | ( | THD * | thd | ) |
Deactivate the timer associated with the statement that was executed.
thd | Thread (session) context. |
|
protectedvirtual |
Restore command properties before execution.
Reimplemented in Sql_cmd_insert_base.
|
static |
|
protectedvirtual |
Save command properties, such as prepared query details and table props.
|
static |
The List<Item_multi_eq> in COND_EQUAL partially overlaps with the argument list in various Item_cond via C-style casts.
However, the hypergraph optimizer can modify the lists in Item_cond (by calling compile()), causing an Item_multi_eq to be replaced with Item_func_eq, and this can cause a List<Item_multi_eq> not to contain Item_multi_eq pointers anymore. This is is obviously bad if anybody wants to actually look into these lists after optimization (in particular, NDB wants this).
Since untangling this spaghetti seems very hard, we solve it by brute force: Make a copy of all the COND_EQUAL lists, so that they no longer reach into the Item_cond. This allows us to modify the Item_cond at will.
|
static |
Check if semijoin's compared types allow materialization.
[in,out] | sj_nest | Semi-join nest containing information about correlated expressions. Set nested_join->sjm.scan_allowed to true if MaterializeScan strategy allowed. Set nested_join->sjm.lookup_allowed to true if MaterializeLookup strategy allowed |
This is a temporary fix for BUG#36752.
There are two subquery materialization strategies for semijoin:
Materialize and do index lookups in the materialized table. See BUG#36752 for description of restrictions we need to put on the compared expressions.
In addition, since indexes are not supported for BLOB columns, this strategy can not be used if any of the columns in the materialized table will be BLOB/GEOMETRY columns. (Note that also columns for non-BLOB values that may be greater in size than CONVERT_IF_BIGGER_TO_BLOB, will be represented as BLOB columns.)
void set_fail_reason_and_raise_error | ( | const LEX * | lex, |
std::string_view | reason | ||
) |
|
private |
Sets the plan's state of the JOIN.
This is always the final step of optimization; starting from this call, we expose the plan to other connections (via EXPLAIN CONNECTION) so the plan has to be final. keyread_optim is set here.
|
private |
Assign set of available (prefix) tables to all tables in query block.
Also set added tables, ie the tables added in each JOIN_TAB compared to the previous JOIN_TAB. This function must be called for every query block after the table order has been determined.
void Sql_cmd_dml::set_query_result | ( | Query_result * | result | ) |
Set query result object for this query statement.
|
static |
|
private |
Set semi-join embedding join nest pointers.
Set pointer to embedding semi-join nest for all semi-joined tables. This is the closest semi-join or anti-join nest. Note that this must be done for every table inside all semi-join nests, even for tables within outer join nests embedded in semi-join nests. A table can never be part of multiple semi-join nests, hence no ambiguities can ever occur. Note also that the pointer is not set for Table_ref objects that are outer join nests within semi-join nests.
|
private |
Set the first_sj_inner_tab and last_sj_inner_tab fields for all tables inside the semijoin nests of the query.
bool set_statement_timer | ( | THD * | thd | ) |
Set the time until the currently running statement is aborted.
thd | Thread (session) context. |
whether timer can be set for the statement or not should be checked before calling set_statement_timer function.
void JOIN_TAB::set_table | ( | TABLE * | t | ) |
Set up join buffering for a specified table, if possible.
tab | joined table to check join buffer usage for |
join | join for which the check is performed |
no_jbuf_after | don't use join buffering after table with this number |
The function finds out whether the table 'tab' can be joined using a join buffer. This check is performed after the best execution plan for 'join' has been chosen. If the function decides that a join buffer can be employed then it selects the most appropriate join cache type, which later will be instantiated by init_join_cache(). If it has already been decided to not use join buffering for this table, no action is taken.
Often it is already decided that join buffering will be used earlier in the optimization process, and this will also ensure that the most correct cost for the operation is calculated, and hence the probability of choosing an optimal join plan is higher. However, some join buffering decisions cannot currently be taken before this stage, hence we need this function to decide the most accurate join buffering strategy.
The result of the check and the type of the join buffer to be used depend on:
If block_nested_loop is turned on, and if all other criteria for using join buffering is fulfilled (see below), then join buffer is used for any join operation (inner join, outer join, semi-join) with 'JT_ALL' access method. In that case, a JOIN_CACHE_BNL type is always employed.
If an index is used to access rows of the joined table and batched_key_access is on, then a JOIN_CACHE_BKA type is employed.
If the function decides that a join buffer can be used to join the table 'tab' then it sets tab->use_join_cache
to reflect the chosen algorithm.
Join buffering is enabled for a few more cases for secondary engine. Currently if blocked nested loop(BNL) is employed for join buffering, it is replaced by hash joins in the executor. So the reasons for disabling join buffering because of the way BNL works are no more valid. This gives us an oppotunity to enable join buffering for more cases. However, we enable it only for secondary engine (in particular for semijoins), because of the following reasons: Secondary engine does not care about the cost based decisions involved in arriving at the best possible semijoin strategy; because it can only interpret a plan using "FirstMatch" strategy and can only do table scans. So the choices are very limited. However, it's not the case for mysql. There are serveral semijoin stratagies that could be picked. And these are picked based on the assumption that a nested-loop join(NLJ) would be used because optimizer currently generates plans only for NLJs and not hash joins. So, when executor replaces with hash joins, the number of rows that would be looked into for a particular semijoin strategy will differ from what the optimizer presumed while picking that strategy. For mysql server, we could enable join buffering for more cases, when a cost model for using hash joins is developed and optimizer could generate plans for hash joins.
JOIN_TAB *first_tab= join->join_tab+join->const_tables; uint n_tables= i-join->const_tables; / * We normally put all preceding tables into the join buffer, except for the constant tables. If we're inside a semi-join materialization nest, e.g. outer_tbl1 outer_tbl2 ( inner_tbl1, inner_tbl2 ) ... ^-- we're here then we need to put into the join buffer only the tables from within the nest. * / if (i >= first_sjm_table && i < last_sjm_table) { n_tables= i - first_sjm_table; // will be >0 if we got here first_tab= join->join_tab + first_sjm_table; }
|
static |
Setup the strategies to eliminate semi-join duplicates.
join | Join to process |
no_jbuf_after | Do not use join buffering after the table with this number |
false | OK |
true | Out of memory error |
Setup the strategies to eliminate semi-join duplicates. At the moment there are 5 strategies:
The join order has "duplicate-generating ranges", and every range is served by one strategy or a combination of FirstMatch with with some other strategy.
"Duplicate-generating range" is defined as a range within the join order that contains all of the inner tables of a semi-join. All ranges must be disjoint, if tables of several semi-joins are interleaved, then the ranges are joined together, which is equivalent to converting
SELECT ... WHERE oe1 IN (SELECT ie1 ...) AND oe2 IN (SELECT ie2 )
to
SELECT ... WHERE (oe1, oe2) IN (SELECT ie1, ie2 ... ...)
.
Applicability conditions are as follows:
Note that MaterializeLookup and MaterializeScan has overlap in their patterns. It may be possible to consolidate the materialization strategies into one.
The choice between the strategies is made by the join optimizer (see advance_sj_state() and fix_semijoin_strategies()). This function sets up all fields/structures/etc needed for execution except for setup/initialization of semi-join materialization which is done in setup_materialized_table().
|
private |
Setup the materialized table for a semi-join nest.
tab | join_tab for the materialized semi-join table |
tableno | table number of materialized table |
inner_pos | information about the first inner table of the subquery |
sjm_pos | information about the materialized semi-join table, to be filled with data. |
Setup execution structures for one semi-join materialization nest:
Filter out ORDER BY items that are equal to constants in WHERE condition.
This function is a limited version of remove_const() for use with non-JOIN statements (i.e. single-table UPDATE and DELETE).
order | Linked list of ORDER BY arguments. |
where | Where condition. |
uint QEP_TAB::sjm_query_block_id | ( | ) | const |
Compares two keyuse elements.
a | first Key_use element |
b | second Key_use element |
Compare Key_use elements so that they are sorted as follows:
true | If a < b. |
false | If a >= b. |
Item * substitute_for_best_equal_field | ( | THD * | thd, |
Item * | cond, | ||
COND_EQUAL * | cond_equal, | ||
JOIN_TAB ** | table_join_idx | ||
) |
Substitute every field reference in a condition by the best equal field and eliminate all multiple equality predicates.
The function retrieves the cond condition and for each encountered multiple equality predicate it sorts the field references in it according to the order of tables specified by the table_join_idx parameter. Then it eliminates the multiple equality predicate by replacing it with the conjunction of simple equality predicates equating every field from the multiple equality to the first field in it, or to the constant, if there is any. After this, the function retrieves all other conjuncted predicates and substitutes every field reference by the field reference to the first equal field or equal constant if there are any.
thd | the session context |
cond | condition to process |
cond_equal | multiple equalities to take into consideration |
table_join_idx | index to tables determining field preference |
bool substitute_gc | ( | THD * | thd, |
Query_block * | query_block, | ||
Item * | where_cond, | ||
ORDER * | group_list, | ||
ORDER * | order | ||
) |
Substitute all expressions in the WHERE condition and ORDER/GROUP lists that match generated columns (GC) expressions with GC fields, if any.
This function does 3 things: 1) Creates list of all GC fields that are a part of a key and the GC expression is a function. All query tables are scanned. If there's no such fields, function exits. 2) By means of Item::compile() WHERE clause is transformed.
thd | thread handle |
query_block | the current select |
where_cond | the WHERE condition, possibly NULL |
group_list | the GROUP BY clause, possibly NULL |
order | the ORDER BY clause, possibly NULL |
bool test_if_cheaper_ordering | ( | const JOIN_TAB * | tab, |
ORDER_with_src * | order, | ||
TABLE * | table, | ||
Key_map | usable_keys, | ||
int | ref_key, | ||
ha_rows | select_limit, | ||
int * | new_key, | ||
int * | new_key_direction, | ||
ha_rows * | new_select_limit, | ||
uint * | new_used_key_parts, | ||
uint * | saved_best_key_parts, | ||
double * | new_read_time | ||
) |
Find a cheaper access key than a given key.
tab | NULL or JOIN_TAB of the accessed table | |
order | Linked list of ORDER BY arguments | |
table | Table if tab == NULL or tab->table() | |
usable_keys | Key map to find a cheaper key in | |
ref_key | 0 <= key < MAX_KEY - key number (hint) to start the search -1 - no key number provided | |
select_limit | LIMIT value, or HA_POS_ERROR if no limit | |
[out] | new_key | Key number if success, otherwise undefined |
[out] | new_key_direction | Return -1 (reverse) or +1 if success, otherwise undefined |
[out] | new_select_limit | Return adjusted LIMIT |
[out] | new_used_key_parts | NULL by default, otherwise return number of new_key prefix columns if success or undefined if the function fails |
[out] | saved_best_key_parts | NULL by default, otherwise preserve the value for further use in ReverseIndexRangeScanIterator |
[out] | new_read_time | NULL by default, otherwise return the cost of access using new_key if success or undefined if the function fails |
|
static |
Test if ORDER BY is a single MATCH function(ORDER BY MATCH) and sort order is descending.
order | pointer to ORDER struct. |
Pointer | to MATCH function if order is 'ORDER BY MATCH() DESC' |
NULL | otherwise |
int test_if_order_by_key | ( | ORDER_with_src * | order_src, |
TABLE * | table, | ||
uint | idx, | ||
uint * | used_key_parts, | ||
bool * | skip_quick | ||
) |
Test if one can use the key to resolve ordering.
order_src | Sort order | |
table | Table to sort | |
idx | Index to check | |
[out] | used_key_parts | NULL by default, otherwise return value for used key parts. |
[out] | skip_quick | Whether found index can be used for backward range scans |
1 | key is ok. |
0 | Key can't be used |
-1 | Reverse key can be used |
|
static |
Test if we can skip ordering by using an index.
If the current plan is to use an index that provides ordering, the plan will not be changed. Otherwise, if an index can be used, the JOIN_TAB / tab->select struct is changed to use the index.
The index must cover all fields in <order>, or it will not be considered.
tab | NULL or JOIN_TAB of the accessed table | |
order | Linked list of ORDER BY arguments | |
select_limit | LIMIT value, or HA_POS_ERROR if no limit | |
no_changes | No changes will be made to the query plan. | |
map | Key_map of applicable indexes. | |
[out] | order_idx | Number of index selected, -1 if no applicable index found |
0 | We have to use filesort to do the sorting |
1 | We can use an index. |
|
static |
Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting.
order | The query block's order clause. |
tab | Current JOIN_TAB. |
ref | Number of key, used for WHERE clause |
ref_key_parts | Index columns used for ref lookup. |
usable_keys | Keys for testing |
Return 1 if second is a subpart of first argument.
If first parts has different direction, change it to second part (group is sorted like order)
|
private |
Test if an index could be used to replace filesort for ORDER BY/GROUP BY.
Investigate whether we may use an ordered index as part of either DISTINCT, GROUP BY or ORDER BY execution. An ordered index may be used for only the first of any of these terms to be executed. This is reflected in the order which we check for test_if_skip_sort_order() below. However we do not check for DISTINCT here, as it would have been transformed to a GROUP BY at this stage if it is a candidate for ordered index optimization. If a decision was made to use an ordered index, the availability if such an access path is stored in 'm_ordered_index_usage' for later use by 'execute' or 'explain'
|
static |
Writes to the optimizer trace information about dependencies between tables.
trace | optimizer trace |
join_tabs | all JOIN_TABs of the join |
table_count | how many JOIN_TABs in the 'join_tabs' array |
|
static |
Check if two items are compatible wrt.
materialization.
outer | Expression from outer query |
inner | Expression from inner query |
true | If subquery types allow materialization. |
false | Otherwise. |
|
private |
|
private |
Update the dependency map for the tables.
|
private |
Update the dependency map for the sort order.
bool JOIN::update_equalities_for_sjm | ( | ) |
Update equalities and keyuse references after semi-join materialization strategy is chosen.
For each multiple equality that contains a field that is selected from a subquery, and that subquery is executed using a semi-join materialization strategy, add the corresponding column in the materialized temporary table to the equality. For each injected semi-join equality that is not converted to multiple equality, replace the reference to the expression selected from the subquery with the corresponding column in the temporary table.
This is needed to properly reflect the equalities that involve injected semi-join equalities when materialization strategy is chosen.
The MaterializeScan semi-join strategy requires some additional processing: All primary tables after the materialized temporary table must be inspected for keyuse objects that point to expressions from the subquery tables. These references must be replaced with references to corresponding columns in the materialized temporary table instead. Those primary tables using ref access will thus be made to depend on the materialized temporary table instead of the subquery tables.
Only the injected semi-join equalities need this treatment, other predicates will be handled correctly by the regular item substitution process.
|
static |
Update keyuse array with all possible keys we can use to fetch rows.
thd | session context | |
[out] | keyuse | Put here ordered array of Key_use structures |
join_tab | Array in table number order | |
tables | Number of tables in join | |
cond | WHERE condition (note that the function analyzes join_tab[i]->join_cond() too) | |
normal_tables | Tables not inner w.r.t some outer join (ones for which we can make ref access based the WHERE clause) | |
query_block | current SELECT | |
[out] | sargables | Array of found sargable candidates |
|
private |
Update info on indexes that can be used for search lookups as reading const tables may has added new sargable predicates.
Check if given expression only uses fields covered by index keyno in the table tbl.
The expression can use any fields in any other tables.
The expression is guaranteed not to be AND or OR - those constructs are handled outside of this function.
Restrict some function types from being pushed down to storage engine: a) Don't push down the triggered conditions with exception for IS_NOT_NULL_COMPL trigger condition since the NULL-complemented rows are added at a later stage in the iterators, so we won't see NULL-complemented rows when evaluating it as an index condition. Nested outer joins execution code may need to evaluate a condition several times (both triggered and untriggered). TODO: Consider cloning the triggered condition and using the copies for:
item | Expression to check |
tbl | The table having the index |
keyno | The index number |
other_tbls_ok | true <=> Fields of other non-const tables are allowed |
bool validate_use_secondary_engine | ( | const LEX * | lex | ) |
Validates a query that uses the secondary engine.
No validations are done if query has not been prepared against the secondary engine.
lex | Parse tree descriptor. |
|
static |
If EXPLAIN or if the –safe-updates option is enabled, add a warning that an index cannot be used for ref access.
If EXPLAIN or if the –safe-updates option is enabled, add a warning for each index that cannot be used for ref access due to either type conversion or different collations on the field used for comparison
Example type conversion (char compared to int):
CREATE TABLE t1 (url char(1) PRIMARY KEY); SELECT * FROM t1 WHERE url=1;
Example different collations (danish vs german2):
CREATE TABLE t1 (url char(1) PRIMARY KEY) collate latin1_danish_ci; SELECT * FROM t1 WHERE url='1' collate latin1_german2_ci;
thd | Thread for the connection that submitted the query |
field | Field used in comparison |
cant_use_index | Indexes that cannot be used for lookup |
const char* antijoin_null_cond = "<ANTIJOIN-NULL>" |