记录mysql的查询优化
查询优化说明:优化器主要分为两个阶段,首先是逻辑查询优化,这个阶段主要是使用关系代数对SQL语句做一些等价变换,对条件表达式进行等价谓词重写、条件简化,对视图进行重写,对子查询进行优化,对连接语义进行了外连接消除、嵌套连接消除等。
其次是物理查询优化。物理查询优化一般分为两种:
基于规则的优化(RBO,Rule-Based Optimizer)
这种方式主要是基于一些预置的规则对查询进行优化。
基于代价的优化(CBO,Cost-Based Optimizer)
这种方式会根据模型计算出各个可能的执行计划的代价,然后选择代价最少的那个。它会利用数据库里面的统计信息来做判断,因此是动态的。
一、使用具体的字段名取代‘*’。由于在查询处理过程当中,查询优化器在setup_wild()函数中会首先将‘*’转化为具体的具体的表中的字段。测试
二、使用具体数据表的字段名取代字段名。即:使用TABLE.FIELD取代FIELD。由于在查询处理中,特别是多表联合查询中,查询优化器在set_field()函数中对不给定具体表名的字段会对全部表进行查询该字段。优化
三、使用GROUP条件取代DISTINCT条件。由于在查询处理中,查询优化器会在优化阶段中调用create_distinct_group()函数,将DISTINCT条件转化为GROUP条件来处理。索引
四、使用LIMIT条件。在查询结果太多的状况下,查询执行阶段会使用LIMIT过滤查询结果,能够有效的下降查询的时间。im
五、‘,’、JOIN、INNER JOIN、CROSS JOIN在MySQL中是等价的。从查询处理逻辑能够看出,最终JOIN、INNER JOIN、CROSS JOIN会转化为多表的联合查询。而且对于内链接查询来讲,ON条件和where条件是同样的,ON条件会在simplify_joins()函数中添加到where条件中。总结
六、LEFT JOIN查询会将左部的表的进行全表扫描,而右部的表中若是没有匹配的记录时,会用NULL值填充。而当数据表不能 NULL表时(与是否有where条件过滤有关),则左部不会所有列出全部记录,并将外链接转化为多表联合查询处理。其余的外链接JOIN查询与LEFT JOIN查询相似,再也不赘述。特别注意,OUTER JOIN的where条件和ON条件有一些区别:ON条件是在生成查询结果以前,进行的过滤;where条件是在查询结果输出过程当中进行的过滤。所以,将过滤条件写到where条件中时,LEFT JOIN查询不会显示左部的全部记录,而是得到符合条件的记录。LEFT JOIN的详细分析和测试,将做为单独的部分呈现。数据
七、STRAIGHT_JOIN查询用于在多表查询时指定表载入的顺序。而在指定载入顺序时,要按照表的关联关系进行指定,不然STAIGHT_JOIN会忽略指定顺序,而经过查询优化器进行优化。若是对查询不能保证指定顺序为最优的状况下,不建议使用STAIGHT_JOIN指定载入的顺序。查询
八、转化子查询为多表联合查询。子查询须要建立临时表,而且查询的临时结果没有任何索引,致使查询性能较低。转化为多表联合查询能够不须要建立临时表,而且能够有效的利用查询数据表的索引。di
核心函数: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:-# Logical transformations:
- Outer to inner joins transformation.
- Equality/constant propagation.
- Partition pruning.
- COUNT(*), MIN(), MAX() constant substitution in case of
implicit grouping.
- ORDER BY optimization.
-# Perform cost-based optimization of table order and access path
selection. See JOIN::make_join_plan()
-# Post-join order optimization:
- Create optimal table conditions from the where clause and the
join conditions.
- Inject outer-join guarding conditions.
- Adjust data access methods after determining table condition
(several times.)
- Optimize ORDER BY/DISTINCT.
-# Code generation
- Set data access functions.
- Try to optimize away sorting/distinct.
- Setup temporary table usage for grouping and/or sorting.@retval 0 Success.
@retval 1 Error, error code saved in member JOIN::error.
int
JOIN::optimize(unsigned char part) //STONEDB UPGRADE
{
uint no_jbuf_after= UINT_MAX;
DBUG_ENTER("JOIN::optimize");
assert(select_lex->leaf_table_count == 0 ||
thd->lex->is_query_tables_locked() ||
select_lex == unit->fake_select_lex);
//assert(tables == 0 &&
// primary_tables == 0 &&
// tables_list == (TABLE_LIST*)1);
//STONEDB UPGRADE BEGIN
//const bool first_optimization= select_lex->first_cond_optimization;
Opt_trace_context * const trace= &thd->opt_trace;
Opt_trace_object trace_wrapper(trace);
Opt_trace_object trace_optimize(trace, "join_optimization");
trace_optimize.add_select_number(select_lex->select_number);
Opt_trace_array trace_steps(trace, "steps");
if(part != 4) {
if (part==0 || part==1)
{
//END
// to prevent double initialization on EXPLAIN
if (optimized)
DBUG_RETURN(0);
Prepare_error_tracker tracker(thd);
DEBUG_SYNC(thd, "before_join_optimize");
THD_STAGE_INFO(thd, stage_optimizing);
if (select_lex->first_execution)
{
if (select_lex->apply_local_transforms(thd, false))
DBUG_RETURN(error= 1);
}
//STONEDB UPGRADE
//END
count_field_types(select_lex, &tmp_table_param, all_fields, false, false);
assert(tmp_table_param.sum_func_count == 0 ||
group_list || implicit_grouping);
if (select_lex->olap == ROLLUP_TYPE && optimize_rollup())
DBUG_RETURN(true);
if (alloc_func_list())
DBUG_RETURN(1);
if (select_lex->get_optimizable_conditions(thd, &where_cond, &having_cond))
DBUG_RETURN(1);
set_optimized();
tables_list= select_lex->get_table_list();
if (select_lex->materialized_derived_table_count)
{
for (TABLE_LIST *tl= select_lex->leaf_tables; tl; tl= tl->next_leaf)
{
if (tl->is_view_or_derived() && tl->optimize_derived(thd))
DBUG_RETURN(1);
}
}
row_limit= ((select_distinct || order || group_list) ?
HA_POS_ERROR : unit->select_limit_cnt);
// m_select_limit is used to decide if we are likely to scan the whole table.
m_select_limit= unit->select_limit_cnt;
if (unit->first_select()->active_options() & OPTION_FOUND_ROWS)
{
calc_found_rows= m_select_limit != HA_POS_ERROR && !select_lex->braces;
}
if (having_cond || calc_found_rows)
m_select_limit= HA_POS_ERROR;
if (unit->select_limit_cnt == 0 && !calc_found_rows)
{
zero_result_cause= "Zero limit";
best_rowcount= 0;
goto setup_subq_exit;
}
}//STONEDB UPGRADE END part=0||part=1
if (where_cond || select_lex->outer_join)
{
if (optimize_cond(thd, &where_cond, &cond_equal,
&select_lex->top_join_list, &select_lex->cond_value,part))//STONEDB UPGRADE
{
error= 1;
DBUG_PRINT("error",("Error from optimize_cond"));
DBUG_RETURN(1);
}
if (select_lex->cond_value == Item::COND_FALSE)
{
zero_result_cause= "Impossible WHERe";
best_rowcount= 0;
goto setup_subq_exit;
}
}
if (having_cond)
{
if (optimize_cond(thd, &having_cond, &cond_equal, NULL,
&select_lex->having_value, part))//STONEDB UPGRADE
{
error= 1;
DBUG_PRINT("error",("Error from optimize_cond"));
DBUG_RETURN(1);
}
if (select_lex->having_value == Item::COND_FALSE)
{
zero_result_cause= "Impossible HAVINg";
best_rowcount= 0;
goto setup_subq_exit;
}
}
//STONEDB UPGRADE
if (part == 1)
{
error= 0;
DBUG_RETURN(0);
}
//END
if (select_lex->partitioned_table_count && prune_table_partitions())
{
error= 1;
DBUG_PRINT("error", ("Error from prune_partitions"));
DBUG_RETURN(1);
}
if (tables_list && implicit_grouping)
{
int res;
if ((res= opt_sum_query(thd, select_lex->leaf_tables, all_fields,
where_cond)))
{
best_rowcount= 0;
if (res == HA_ERR_KEY_NOT_FOUND)
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
goto setup_subq_exit;
}
if (res > 1)
{
error= res;
DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
}
if (res < 0)
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
goto setup_subq_exit;
}
DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
best_rowcount= 1;
const_tables= tables= primary_tables= select_lex->leaf_table_count;
if (where_cond && !thd->lex->describe)
{
Item *table_independent_conds=
make_cond_for_table(where_cond, PSEUDO_TABLE_BITS, 0, 0);
DBUG_EXECUTE("where",
print_where(table_independent_conds,
"where after opt_sum_query()",
QT_ORDINARY););
where_cond= table_independent_conds;
}
goto setup_subq_exit;
}
}
if (!tables_list)
{
DBUG_PRINT("info",("No tables"));
best_rowcount= 1;
error= 0;
if (make_tmp_tables_info())
DBUG_RETURN(1);
count_field_types(select_lex, &tmp_table_param, all_fields, false, false);
// Make plan visible for EXPLAIN
set_plan_state(NO_TABLES);
DBUG_RETURN(0);
}
error= -1; // Error is sent to client
sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
if ((where_cond || group_list || order) &&
substitute_gc(thd, select_lex, where_cond, group_list, order))
{
// We added hidden fields to the all_fields list, count them.
count_field_types(select_lex, &tmp_table_param, select_lex->all_fields,
false, false);
}
// Set up join order and initial access paths
THD_STAGE_INFO(thd, stage_statistics);
if (make_join_plan())
{
if (thd->killed)
thd->send_kill_message();
DBUG_PRINT("error",("Error: JOIN::make_join_plan() failed"));
DBUG_RETURN(1);
}
// At this stage, join_tab==NULL, JOIN_TABs are listed in order by best_ref.
ASSERT_BEST_REF_IN_JOIN_ORDER(this);
if (zero_result_cause)
goto setup_subq_exit;
if (rollup.state != ROLLUP::STATE_NONE)
{
if (rollup_process_const_fields())
{
DBUG_PRINT("error", ("Error: rollup_process_fields() failed"));
DBUG_RETURN(1);
}
// JOIN::optimize_rollup() may set quick_group=0, and we must not undo that.
const uint save_quick_group= tmp_table_param.quick_group;
count_field_types(select_lex, &tmp_table_param, all_fields, false, false);
tmp_table_param.quick_group= save_quick_group;
}
else
{
select_distinct&= !plan_is_const();
}
if (const_tables && !thd->locked_tables_mode &&
!(select_lex->active_options() & SELECT_NO_UNLOCK )&& part!=3) //STONEDB UPGRADE
{
TABLE *ct[MAX_TABLES];
for (uint i= 0; i < const_tables; i++)
ct[i]= best_ref[i]->table();
mysql_unlock_some_tables(thd, ct, const_tables);
}
if (!where_cond && select_lex->outer_join)
{
where_cond=new Item_int((longlong) 1,1); // Always true
}
error= 0;
if (where_cond)
{
where_cond= substitute_for_best_equal_field(where_cond, cond_equal,
map2table);
if (thd->is_error())
{
error= 1;
DBUG_PRINT("error",("Error from substitute_for_best_equal"));
DBUG_RETURN(1);
}
where_cond->update_used_tables();
DBUG_EXECUTE("where",
print_where(where_cond,
"after substitute_best_equal",
QT_ORDINARY););
}
for (uint i= const_tables; i < tables ; ++i)
{
JOIN_TAB *const tab= best_ref[i];
if (tab->position() && tab->join_cond())
{
tab->set_join_cond(substitute_for_best_equal_field(tab->join_cond(),
tab->cond_equal,
map2table));
if (thd->is_error())
{
error= 1;
DBUG_PRINT("error",("Error from substitute_for_best_equal"));
DBUG_RETURN(1);
}
tab->join_cond()->update_used_tables();
}
}
//STONEDB UPGRADE BEGIN
// this is end of part=3 and beginning of part=4
if(part == 3) {
DBUG_RETURN(0); // error == 0
}
//END
}// end of if(part!=4)
if (init_ref_access())
{
error= 1;
DBUG_PRINT("error",("Error from init_ref_access"));
DBUG_RETURN(1);
}
// Update table dependencies after assigning ref access fields
update_depend_map();
THD_STAGE_INFO(thd, stage_preparing);
if (make_join_select(this, where_cond))
{
if (thd->is_error())
DBUG_RETURN(1);
zero_result_cause=
"Impossible WHERe noticed after reading const tables";
goto setup_subq_exit;
}
if (select_lex->query_result()->initialize_tables(this))
{
DBUG_PRINT("error",("Error: initialize_tables() failed"));
DBUG_RETURN(1); // error == -1
}
error= -1;
if (optimize_distinct_group_order())
DBUG_RETURN(true);
if ((select_lex->active_options() & SELECT_NO_JOIN_CACHE) ||
select_lex->ftfunc_list->elements)
no_jbuf_after= 0;
if (select_lex->has_ft_funcs() && optimize_fts_query())
DBUG_RETURN(1);
child_subquery_can_materialize= true;
if (having_cond && const_table_map && !having_cond->with_sum_func)
{
having_cond->update_used_tables();
if (remove_eq_conds(thd, having_cond, &having_cond,
&select_lex->having_value, part))
{
error= 1;
DBUG_PRINT("error",("Error from remove_eq_conds"));
DBUG_RETURN(1);
}
if (select_lex->having_value == Item::COND_FALSE)
{
having_cond= new Item_int((longlong) 0,1);
zero_result_cause= "Impossible HAVINg noticed after reading const tables";
goto setup_subq_exit;
}
}
if (!plan_is_const() && cache_const_exprs())
DBUG_RETURN(1);
// See if this subquery can be evaluated with subselect_indexsubquery_engine
if (const int ret= replace_index_subquery())
{
set_plan_state(PLAN_READY);
DBUG_RETURN(ret < 0);
}
{
if (!plan_is_const())
{
const TABLE * const first= best_ref[const_tables]->table();
if ((first->force_index_order && order) ||
(first->force_index_group && group_list))
no_jbuf_after= 0;
}
bool simple_sort= true;
// Check whether join cache could be used
for (uint i= const_tables; i < tables; i++)
{
JOIN_TAB *const tab= best_ref[i];
if (!tab->position())
continue;
if (setup_join_buffering(tab, this, no_jbuf_after))
DBUG_RETURN(true);
if (tab->use_join_cache() != JOIN_CACHE::ALG_NONE)
simple_sort= false;
assert(tab->type() != JT_FT ||
tab->use_join_cache() == JOIN_CACHE::ALG_NONE);
}
if (!simple_sort)
{
simple_order= simple_group= false;
}
}
if (!plan_is_const() && order)
{
for (ORDER *tmp_order= order; tmp_order ; tmp_order=tmp_order->next)
{
Item *item= *tmp_order->item;
if (item->is_expensive())
{
simple_order= simple_group= false;
break;
}
}
}
need_tmp= ((!plan_is_const() &&
((select_distinct || (order && !simple_order) ||
(group_list && !simple_group)) ||
(group_list && order) ||
(select_lex->active_options() & OPTION_BUFFER_RESULT))) ||
(rollup.state != ROLLUP::STATE_NONE && select_distinct));
DBUG_EXECUTE("info", TEST_join(this););
if (!plan_is_const())
{
JOIN_TAB *tab= best_ref[const_tables];
if ((order || group_list) &&
tab->type() != JT_ALL &&
tab->type() != JT_FT &&
tab->type() != JT_REF_OR_NULL &&
((order && simple_order) || (group_list && simple_group)))
{
if (add_ref_to_table_cond(thd,tab)) {
DBUG_RETURN(1);
}
}
// Test if we can use an index instead of sorting
test_skip_sort();
}
if (alloc_qep(tables))
DBUG_RETURN(error= 1);
if (make_join_readinfo(this, no_jbuf_after))
DBUG_RETURN(1);
if (make_tmp_tables_info())
DBUG_RETURN(1);
// At this stage, we have fully set QEP_TABs; JOIN_TABs are unaccessible,
// pushed joins(see below) are still allowed to change the QEP_TABs
if (!plan_is_single_table() && !plan_is_const())
{
const AQP::Join_plan plan(this);
if (ha_make_pushed_joins(thd, &plan))
DBUG_RETURN(1);
}
// Update m_current_query_cost to reflect actual need of filesort.
if (sort_cost > 0.0 && !explain_flags.any(ESP_USING_FILESORT))
{
best_read-= sort_cost;
sort_cost= 0.0;
if (thd->lex->is_single_level_stmt())
thd->m_current_query_cost= best_read;
}
count_field_types(select_lex, &tmp_table_param, all_fields, false, false);
// Make plan visible for EXPLAIN
set_plan_state(PLAN_READY);
DEBUG_SYNC(thd, "after_join_optimize");
error= 0;
DBUG_RETURN(0);
setup_subq_exit:
assert(zero_result_cause != NULL);
child_subquery_can_materialize= true;
trace_steps.end(); // because all steps are done
Opt_trace_object(trace, "empty_result")
.add_alnum("cause", zero_result_cause);
having_for_explain= having_cond;
error= 0;
if (!qep_tab && best_ref)
{
if (alloc_qep(tables))
DBUG_RETURN(1);
unplug_join_tabs();
}
set_plan_state(ZERO_RESULT);
DBUG_RETURN(0);
}
调用堆栈:
(gdb) bt
#0 JOIN::optimize (this=0x7ff7c80089d8, part=1 ' 01') at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/sql_optimizer.cc:140
#1 0x0000000002d43ec5 in stonedb::core::optimize_select (thd=0x7ff7c80125f0, select_options=2147748608, result=0x7ff7c80083a0, select_lex=0x7ff7c8010720,
optimize_after_sdb=@0x7ffa6d2dad0c: 1, free_join=@0x7ffa6d2dad10: 1) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/storage/stonedb/core/engine_execute.cpp:352
#2 0x0000000002d43778 in stonedb::core::Engine::HandleSelect (this=0x73099c0, thd=0x7ff7c80125f0, lex=0x7ff7c8014918, result=@0x7ffa6d2dad18: 0x7ff7c80083a0, setup_tables_done_option=0,
res=@0x7ffa6d2dad14: 0, optimize_after_sdb=@0x7ffa6d2dad0c: 1, sdb_free_join=@0x7ffa6d2dad10: 1, with_insert=0)
at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/storage/stonedb/core/engine_execute.cpp:225
#3 0x0000000002e2bfaf in stonedb::dbhandler::SDB_HandleSelect (thd=0x7ff7c80125f0, lex=0x7ff7c8014918, result=@0x7ffa6d2dad18: 0x7ff7c80083a0, setup_tables_done_option=0,
res=@0x7ffa6d2dad14: 0, optimize_after_sdb=@0x7ffa6d2dad0c: 1, sdb_free_join=@0x7ffa6d2dad10: 1, with_insert=0)
at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/storage/stonedb/handler/ha_rcengine.cpp:82
#4 0x000000000246f92a in execute_sqlcom_select (thd=0x7ff7c80125f0, all_tables=0x7ff7c800bd00) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/sql_parse.cc:5182
#5 0x0000000002468cae in mysql_execute_command (thd=0x7ff7c80125f0, first_level=true) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/sql_parse.cc:2831
#6 0x00000000024708f3 in mysql_parse (thd=0x7ff7c80125f0, parser_state=0x7ffa6d2dbeb0) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/sql_parse.cc:5621
#7 0x0000000002465b8b in dispatch_command (thd=0x7ff7c80125f0, com_data=0x7ffa6d2dc650, command=COM_QUERY) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/sql_parse.cc:1495
#8 0x0000000002464ab7 in do_command (thd=0x7ff7c80125f0) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/sql_parse.cc:1034
#9 0x00000000025976d3 in handle_connection (arg=0x86c8b30) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/sql/conn_handler/connection_handler_per_thread.cc:313
#10 0x0000000002c7b304 in pfs_spawn_thread (arg=0x871c4d0) at /home/jenkins/workspace/stonedb5.7-zsl-centos7.9-vm/storage/perfschema/pfs.cc:2197
#11 0x00007ffa7675aea5 in start_thread () from /lib64/libpthread.so.0
#12 0x00007ffa74b91b0d in clone () from /lib64/libc.so.6
join值:
(gdb) p *this
$2 = { = {}, select_lex = 0x7ff7c8010720, unit = 0x7ff7c8010a08, thd = 0x7ff7c80125f0, join_list = 0x0, select_options = 0, join_tab = 0x0, qep_tab = 0x0,
best_ref = 0x0, map2table = 0x0, sort_by_table = 0x0, tables = 0, primary_tables = 0, const_tables = 0, tmp_tables = 0, send_group_parts = 1, sort_and_group = false,
first_record = false, grouped = true, do_send_rows = true, all_table_map = 0, const_table_map = 0, found_const_table_map = 0, send_records = 0, found_records = 0, examined_rows = 0,
row_limit = 0, m_select_limit = 0, fetch_limit = 18446744073709551615, best_positions = 0x0, positions = 0x0, first_select = 0x24233cb , best_read = 0,
best_rowcount = 2, sort_cost = 0, fields = 0x7ff7c8010858, group_fields = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008ac0,
elements = 0}, }, group_fields_cache = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008ad8,
elements = 0}, }, sum_funcs = 0x0, sum_funcs_end = 0x0, sum_funcs2 = 0x0, sum_funcs_end2 = 0x0, tmp_table_param = { = {},
copy_funcs = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008b18, elements = 0}, }, copy_field = 0x0,
copy_field_end = 0x0, group_buff = 0x0, items_to_copy = 0x0, recinfo = 0x0, start_recinfo = 0x0, keyinfo = 0x0, end_write_records = 18446744073709551615, field_count = 0,
func_count = 0, sum_func_count = 0, hidden_field_count = 0, group_parts = 0, group_length = 0, group_null_parts = 0, quick_group = 1, outer_sum_func_count = 0,
using_outer_summary_function = false, table_charset = 0x0, schema_table = false, precomputed_group_by = false, force_copy_fields = false, skip_create_table = false,
bit_fields_as_long = false, can_use_pk_for_unique = true}, lock = 0x7ff7c894b5e0, rollup = {state = st_rollup::STATE_NONE, null_items = {m_array = 0x0, m_size = 0},
ref_pointer_arrays = 0x0, fields = 0x0}, implicit_grouping = false, select_distinct = false, group_optimized_away = false, simple_order = false, simple_group = false,
ordered_index_usage = JOIN::ordered_index_void, no_order = false, skip_sort_order = false, need_tmp = false, keyuse_array = {> = {
m_root = 0x7ff7c8015330, m_array = 0x0, m_size = 0, m_capacity = 0}, }, all_fields = @0x7ff7c8010880,
tmp_all_fields1 = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008c10, elements = 0}, },
tmp_all_fields2 = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008c28, elements = 0}, },
tmp_all_fields3 = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008c40, elements = 0}, },
tmp_fields_list1 = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008c58, elements = 0}, },
tmp_fields_list2 = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008c70, elements = 0}, },
tmp_fields_list3 = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008c88, elements = 0}, },
fields_list = @0x7ff7c8010858, error = 0, order = {order = 0x7ff7c800b9e0, src = ESC_ORDER_BY, flags = 1}, group_list = {order = 0x7ff7c800b878, src = ESC_GROUP_BY, flags = 1},
explain_flags = {sorts = " 00 01 01 00"}, where_cond = 0x1, having_cond = 0x1, having_for_explain = 0x1, tables_list = 0x1, cond_equal = 0x0, return_tab = 0 ' 00', ref_ptrs = {
m_array = 0x7ff7c80083d8, m_size = 23}, items0 = {m_array = 0x0, m_size = 0}, items1 = {m_array = 0x0, m_size = 0}, items2 = {m_array = 0x0, m_size = 0}, items3 = {m_array = 0x0,
m_size = 0}, current_ref_ptrs = {m_array = 0x0, m_size = 0}, zero_result_cause = 0x0, child_subquery_can_materialize = false, allow_outer_refs = false,
sj_tmp_tables = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008d78, elements = 0}, },
sjm_exec_list = { = { = {}, first = 0x489f510 , last = 0x7ff7c8008d90, elements = 0}, }, set_group_rpa = false,
group_sent = false, calc_found_rows = false, with_json_agg = false, optimized = false, executed = false, plan_state = JOIN::NO_PLAN}
(gdb) set print pretty
(gdb)
(gdb) p *this
$3 = {
= {},
members of JOIN:
select_lex = 0x7ff7c8010720,
unit = 0x7ff7c8010a08,
thd = 0x7ff7c80125f0,
join_list = 0x0,
select_options = 0,
join_tab = 0x0,
qep_tab = 0x0,
best_ref = 0x0,
map2table = 0x0,
sort_by_table = 0x0,
tables = 0,
primary_tables = 0,
const_tables = 0,
tmp_tables = 0,
send_group_parts = 1,
sort_and_group = false,
first_record = false,
grouped = true,
do_send_rows = true,
all_table_map = 0,
const_table_map = 0,
found_const_table_map = 0,
send_records = 0,
found_records = 0,
examined_rows = 0,
row_limit = 0,
m_select_limit = 0,
fetch_limit = 18446744073709551615,
best_positions = 0x0,
positions = 0x0,
first_select = 0x24233cb ,
best_read = 0,
best_rowcount = 2,
sort_cost = 0,
fields = 0x7ff7c8010858,
group_fields = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008ac0,
elements = 0
}, },
group_fields_cache = {
= {
= {},
members of base_list:
first = 0x489f510 ,
---Type to continue, or q to quit---
last = 0x7ff7c8008ad8,
elements = 0
}, },
sum_funcs = 0x0,
sum_funcs_end = 0x0,
sum_funcs2 = 0x0,
sum_funcs_end2 = 0x0,
tmp_table_param = {
= {},
members of Temp_table_param:
copy_funcs = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008b18,
elements = 0
}, },
copy_field = 0x0,
copy_field_end = 0x0,
group_buff = 0x0,
items_to_copy = 0x0,
recinfo = 0x0,
start_recinfo = 0x0,
keyinfo = 0x0,
end_write_records = 18446744073709551615,
field_count = 0,
func_count = 0,
sum_func_count = 0,
hidden_field_count = 0,
group_parts = 0,
group_length = 0,
group_null_parts = 0,
quick_group = 1,
outer_sum_func_count = 0,
using_outer_summary_function = false,
table_charset = 0x0,
schema_table = false,
precomputed_group_by = false,
force_copy_fields = false,
skip_create_table = false,
bit_fields_as_long = false,
can_use_pk_for_unique = true
},
lock = 0x7ff7c894b5e0,
rollup = {
state = st_rollup::STATE_NONE,
null_items = {
m_array = 0x0,
m_size = 0
},
---Type to continue, or q to quit---
ref_pointer_arrays = 0x0,
fields = 0x0
},
implicit_grouping = false,
select_distinct = false,
group_optimized_away = false,
simple_order = false,
simple_group = false,
ordered_index_usage = JOIN::ordered_index_void,
no_order = false,
skip_sort_order = false,
need_tmp = false,
keyuse_array = {
> = {
m_root = 0x7ff7c8015330,
m_array = 0x0,
m_size = 0,
m_capacity = 0
}, },
all_fields = @0x7ff7c8010880,
tmp_all_fields1 = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008c10,
elements = 0
}, },
tmp_all_fields2 = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008c28,
elements = 0
}, },
tmp_all_fields3 = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008c40,
elements = 0
}, },
tmp_fields_list1 = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008c58,
elements = 0
---Type to continue, or q to quit---
}, },
tmp_fields_list2 = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008c70,
elements = 0
}, },
tmp_fields_list3 = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008c88,
elements = 0
}, },
fields_list = @0x7ff7c8010858,
error = 0,
order = {
order = 0x7ff7c800b9e0,
src = ESC_ORDER_BY,
flags = 1
},
group_list = {
order = 0x7ff7c800b878,
src = ESC_GROUP_BY,
flags = 1
},
explain_flags = {
sorts = " 00 01 01 00"
},
where_cond = 0x1,
having_cond = 0x1,
having_for_explain = 0x1,
tables_list = 0x1,
cond_equal = 0x0,
return_tab = 0 ' 00',
ref_ptrs = {
m_array = 0x7ff7c80083d8,
m_size = 23
},
items0 = {
m_array = 0x0,
m_size = 0
},
items1 = {
m_array = 0x0,
m_size = 0
},
items2 = {
---Type to continue, or q to quit---
m_array = 0x0,
m_size = 0
},
items3 = {
m_array = 0x0,
m_size = 0
},
current_ref_ptrs = {
m_array = 0x0,
m_size = 0
},
zero_result_cause = 0x0,
child_subquery_can_materialize = false,
allow_outer_refs = false,
sj_tmp_tables = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008d78,
elements = 0
}, },
sjm_exec_list = {
= {
= {},
members of base_list:
first = 0x489f510 ,
last = 0x7ff7c8008d90,
elements = 0
}, },
set_group_rpa = false,
group_sent = false,
calc_found_rows = false,
with_json_agg = false,
optimized = false,
executed = false,
plan_state = JOIN::NO_PLAN
}



