1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-18478 ANALYZE for statement should show selectivity of ICP, part#2

Part#2, variant 2: Make the printed r_ values in JSON output consistent.
After this patch, ANALYZE output has:

- r_index_rows (NEW) - Observed number of rows before ICP or Rowid Filtering
  checks. This is a per-scan average. like r_rows and "rows" are.

- r_rows (AS BEFORE) - Observed number of rows after ICP and Rowid Filtering.

- r_icp_filtered (NEW) - Observed selectivity of ICP condition.

- (AS BEFORE) observed selectivity of Rowid Filter is in
  $.rowid_filter.r_selectivity_pct

- r_total_filtered - Observed combined selectivity: fraction of rows left
  after applying ICP condition, Rowid Filter, and attached_condition.
  This is now comparable with "filtered" and is printed right after it.

- r_filtered (AS BEFORE) - Observed selectivity of "attached_condition".

Tabular ANALYZE output is not changed. Note that JSON's r_filtered and
r_rows have the same meanings as before and have the same meaning as in
tabular output.
This commit is contained in:
Sergei Petrunia
2024-02-26 11:32:38 +03:00
parent e87d1e391b
commit 0940a96940
32 changed files with 912 additions and 449 deletions

View File

@@ -1804,28 +1804,9 @@ void Explain_table_access::tag_to_json(Json_writer *writer,
writer->add_member("open_frm_only").add_bool(true);
break;
case ET_USING_INDEX_CONDITION:
writer->add_member("index_condition");
write_item(writer, pushed_index_cond);
break;
case ET_USING_INDEX_CONDITION_BKA:
writer->add_member("index_condition_bka");
write_item(writer, pushed_index_cond);
break;
case ET_USING_WHERE:
{
/*
We are printing the condition that is checked when scanning this
table.
- when join buffer is used, it is cache_cond.
- in other cases, it is where_cond.
*/
Item *item= bka_type.is_using_jbuf()? cache_cond: where_cond;
if (item)
{
writer->add_member("attached_condition");
write_item(writer, item);
}
}
/* Conditions are printed outside of this function */
break;
case ET_USING_INDEX:
writer->add_member("using_index").add_bool(true);
@@ -2089,9 +2070,47 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if (rows_set)
writer->add_member("rows").add_ull(rows);
/* `r_rows` */
double r_index_rows; /* protected by have_icp_or_rowid_filter */
bool r_index_rows_is_zero; /* also protected by have_icp_or_rowid_filter */
bool have_icp_or_rowid_filter= false;
/* `r_index_rows` and `r_rows` */
if (is_analyze)
{
/*
r_index_rows is the number of rows enumerated in the index before
any kind of checking. The number is the average across all scans.
*/
double loops;
if (tracker.get_loops())
loops = rows2double(tracker.get_loops());
else
loops= 1.0;
handler *file= handler_for_stats;
if (file && file->handler_stats && file->pushed_idx_cond)
{
/*
Pushed Index Condition is checked before checking the Rowid Filter,
so try getting it first.
*/
ulonglong val= file->handler_stats->icp_attempts;
r_index_rows_is_zero= (val == 0);
r_index_rows= val / loops;
have_icp_or_rowid_filter= true;
}
else if (rowid_filter)
{
/* If ICP wasn't used, get the number from Rowid Filter */
uint val= rowid_filter->tracker->get_container_lookups();
r_index_rows_is_zero= (val == 0);
r_index_rows= val / loops;
have_icp_or_rowid_filter= true;
}
/* Print r_index_rows only if ICP and/or Rowid Filter were used */
if (have_icp_or_rowid_filter)
writer->add_member("r_index_rows").add_double(r_index_rows);
writer->add_member("r_rows");
if (pre_join_sort)
{
@@ -2124,33 +2143,99 @@ void Explain_table_access::print_explain_json(Explain_query *query,
writer->add_member("r_other_time_ms").add_double(extra_time_tracker.get_time_ms());
}
trace_engine_stats(handler_for_stats, writer);
print_r_icp_filtered(handler_for_stats, tracker, writer);
}
/* `filtered` */
if (filtered_set)
writer->add_member("filtered").add_double(filtered);
/* `r_filtered` */
bool have_r_filtered= false;
double r_filtered;
/* Compute value of `r_filtered` - filtered of attached_condition */
if (is_analyze)
{
writer->add_member("r_filtered");
if (pre_join_sort)
{
/* Get r_filtered value from filesort */
if (pre_join_sort->tracker.get_r_loops())
writer->add_double(pre_join_sort->tracker.get_r_filtered()*100);
else
writer->add_null();
{
have_r_filtered= true;
r_filtered= pre_join_sort->tracker.get_r_filtered()*100;
}
}
else
{
/* Get r_filtered from the NL-join runtime */
if (tracker.has_scans())
writer->add_double(tracker.get_filtered_after_where()*100.0);
else
writer->add_null();
{
have_r_filtered= true;
r_filtered= tracker.get_filtered_after_where()*100.0;
}
}
/*
Add r_total_filtered, as combined "filtered" of all kinds of filtering:
Rowid Filter, Index Condition Pushdown, attached condition.
*/
double r_total_filtered;
if (have_icp_or_rowid_filter)
{
double out_rows;
if (pre_join_sort)
out_rows= pre_join_sort->tracker.get_avg_returned_rows();
else
out_rows= tracker.get_avg_rows_after_where();
if (r_index_rows_is_zero)
r_total_filtered= 100.0;
else
r_total_filtered= out_rows* 100.0 / r_index_rows;
}
else if (have_r_filtered)
r_total_filtered= r_filtered;
writer->add_member("r_total_filtered");
if (have_r_filtered)
writer->add_double(r_total_filtered);
else
writer->add_null();
}
/*
`index_condition[_bka]`
*/
if (pushed_index_cond)
{
writer->add_member(bka_type.is_bka? "index_condition_bka": "index_condition");
write_item(writer, pushed_index_cond);
if (is_analyze)
print_r_icp_filtered(handler_for_stats, writer);
}
/* `attached_condition` */
{
/*
we are printing the condition that is checked when scanning this
table.
- when join buffer is used, it is cache_cond.
- in other cases, it is where_cond.
*/
Item *item= bka_type.is_using_jbuf()? cache_cond: where_cond;
if (item)
{
writer->add_member("attached_condition");
write_item(writer, item);
}
}
/* `r_filtered` - filtered of attached_condition */
if (is_analyze)
{
writer->add_member("r_filtered");
if (have_r_filtered)
writer->add_double(r_filtered);
else
writer->add_null();
}
for (int i=0; i < (int)extra_tags.elements(); i++)
@@ -2787,12 +2872,12 @@ void Explain_update::print_explain_json(Explain_query *query,
if (mrr_type.length() != 0)
writer->add_member("mrr_type").add_str(mrr_type.ptr());
double UNINIT_VAR(r_filtered); /* set and used when is_analyze==true */
if (is_analyze)
{
if (doing_buffering)
{
ha_rows r_rows;
double r_filtered;
if (is_using_filesort())
{
@@ -2811,7 +2896,8 @@ void Explain_update::print_explain_json(Explain_query *query,
r_filtered= buf_tracker.get_filtered_after_where() * 100.0;
}
writer->add_member("r_rows").add_ull(r_rows);
writer->add_member("r_filtered").add_double(r_filtered);
/* Currently r_total_filtered == r_filtered for DMLs */
writer->add_member("r_total_filtered").add_double(r_filtered);
}
else /* Not doing buffering */
{
@@ -2822,8 +2908,9 @@ void Explain_update::print_explain_json(Explain_query *query,
writer->add_null();
/* There is no 'filtered' estimate in UPDATE/DELETE atm */
double r_filtered= tracker.get_filtered_after_where() * 100.0;
writer->add_member("r_filtered").add_double(r_filtered);
r_filtered= tracker.get_filtered_after_where() * 100.0;
/* Currently r_total_filtered == r_filtered for DMLs */
writer->add_member("r_total_filtered").add_double(r_filtered);
}
if (table_tracker.has_timed_statistics())
@@ -2841,6 +2928,9 @@ void Explain_update::print_explain_json(Explain_query *query,
write_item(writer, where_cond);
}
if (is_analyze)
writer->add_member("r_filtered").add_double(r_filtered);
/*** The part of plan that is before the buffering/sorting ends here ***/
if (is_using_filesort())
writer->end_object();