1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00
Commit Graph

230 Commits

Author SHA1 Message Date
bsrikanth-mariadb
fea7a9934c MDEV-16462: explain format=json produces illegal json text
The attached_condition field of the produced json text had
"String with illegal unicode symbol" instead of the proper unicode
value.

The reason is that, the item field when being written to the json
writer in write_item(), used a String with charset my_charset_bin,
and that prevented the string from being escaped.

Solution is to change: -
1. charset to my_charset_utf8mb4_bin in sql_explain.cc.
2. Item::print_value(), handle string type specially if
   the charset is my_charset_bin by appending hex value.
2026-07-15 19:23:17 +05:30
Mohammad Tafzeel Shams
91c4460e25 MDEV-38305: Expose adaptive hash index statistics in ANALYZE FORMAT=JSON
Expose InnoDB's Adaptive Hash Index (AHI) statistics through ANALYZE
FORMAT=JSON output and global status variables to provide query-level
and system-level visibility into AHI usage and effectiveness.
This allows DBAs and developers to monitor how well
the adaptive hash index is serving their workloads on a per-query basis.

The r_ahi_stats object (nested inside r_engine_stats) now reports four
key metrics: ahi_searches (successful AHI lookups), ahi_searches_btree
(AHI misses requiring B-tree fallback), ahi_rows_added (rows inserted
into AHI), and ahi_pages_added (pages indexed by AHI). These same
metrics are exposed globally via innodb_status_variables.

Transaction-local tracking eliminates contention by accumulating
statistics in trx_t fields (n_sea, n_non_sea, n_ahi_rows_added,
n_ahi_pages_added) and aggregating them into global atomic counters
during trx_t::commit_cleanup() and trx_t::free(),
following the pattern established for buf_pool.stat.n_page_gets.

AHI counters are now organized as data members of the btr_sea structure
where they logically belong, using anonymous unions to enable both
atomic writes and direct non-atomic reads.

- btr_ahi_inc_searches(): Increment trx->n_sea when AHI lookup succeeds.
- btr_ahi_inc_searches_btree(): Increment trx->n_non_sea when AHI lookup
  fails and falls back to B-tree search.
- btr_ahi_inc_rows_added(): Increment trx->n_ahi_rows_added when rows
  are added to the adaptive hash index structure.
- btr_ahi_inc_pages_added(): Increment trx->n_ahi_pages_added when new
  pages are indexed by AHI.
- btr_cur_t::search_leaf(): Call btr_ahi_inc_searches() on successful
  AHI hit and btr_ahi_inc_searches_btree() on AHI miss.
- btr_sea: Add four counter members with anonymous unions to allow atomic
  writes and lockless reads: hit_count/hit_count_nonatomic (successful AHI
  lookups), miss_count/miss_count_nonatomic (B-tree searches after AHI miss),
  rows_added/rows_added_nonatomic (rows added to AHI), and
  pages_added/pages_added_nonatomic (pages added to AHI). Also includes
  hit_count_old and miss_count_old variant for computing deltas in monitor
  output.
- btr0cur.h/btr0cur.cc: Remove global declarations and definitions of
  btr_cur_n_sea, btr_cur_n_non_sea, btr_cur_n_sea_old, btr_cur_n_non_sea_old,
  btr_ahi_n_rows_added, and btr_ahi_n_pages_added as they are now data
  members of btr_sea.
- export_var_t: Remove innodb_ahi_hit, innodb_ahi_miss, innodb_ahi_rows_added,
  and innodb_ahi_pages_added members. MySQL status variables now point
  directly to btr_search counters.
- innodb_status_variables[]: Change AHI status variable pointers from
  &export_vars.innodb_ahi_* to &btr_search.*_nonatomic, enabling zero-copy
  reads: adaptive_hash_hash_searches points to &btr_search.hit_count_nonatomic,
  adaptive_hash_non_hash_searches to &btr_search.miss_count_nonatomic,
  adaptive_hash_rows_added to &btr_search.rows_added_nonatomic, and
  adaptive_hash_pages_added to &btr_search.pages_added_nonatomic.
- MONITOR_OVLD_ADAPTIVE_HASH_ROW_ADDED, MONITOR_OVLD_ADAPTIVE_HASH_PAGE_ADDED:
  Convert monitor counters to "overload" type that read from atomic counters
  btr_search.rows_added and btr_search.pages_added respectively instead of
  maintaining separate statistics.
- trx_t::commit_cleanup() and trx_t::free(): Update transaction cleanup to
  increment btr_search.hit_count, btr_search.miss_count, btr_search.rows_added,
  and btr_search.pages_added instead of the old global counters.
- trace_engine_stats(): Output r_ahi_stats object with all four AHI
  counters in JSON format when any AHI activity is detected during query
  execution.
- ha_handler_stats: Added ahi_searches, ahi_searches_btree, ahi_rows_added,
  and ahi_pages_added fields to track per-query AHI statistics.
- Add mtr parameter to btr_search_move_or_delete_hash_entries(),
  btr_cur_t::search_info_update(), btr_search_update_hash_on_insert(),
  btr_search_update_hash_ref(), btr_search_info_update_hash(), and
  btr_search_build_page_hash_index() to allow updating AHI statistics.
- ahi_stats.test: Comprehensive verification of AHI statistics reporting
  across different scenarios: insufficient accesses (no AHI build),
  threshold triggering (AHI construction), heavy warmup (full AHI
  utilization), and disabled AHI (verify zero statistics).
- check_ahi_status.inc: Reusable include file for executing queries with
  configurable warmup repetitions and extracting AHI statistics from
  ANALYZE FORMAT=JSON output using JSON path expressions.
2026-06-14 23:40:25 +05:30
Marko Mäkelä
55b3dced05 Merge 11.8 into 12.3 2026-04-02 09:15:17 +03:00
Marko Mäkelä
1a144f713a Merge 11.4 into 11.8 2026-04-01 15:03:59 +03:00
Marko Mäkelä
7c5cac0d51 Merge 10.11 into 11.4 2026-04-01 10:49:05 +03:00
bsrikanth-mariadb
b5cd63082b MDEV-37904: Use of un-initialized value
valgrind reported use of an un-initialized value, when trying to write
analyzed plan to json. Instead of fetching c_str() from the string
object and passing it to the writer object's add_string() method, one could
use an overridden add_string() that accepts a different string object.
This would avoid the valgrind warnings.
2026-03-26 21:46:35 +05:30
Yuchen Pei
a9f384b7c5 MDEV-37330 Indicate in ANALYZE FORMAT=JSON index scan method used for partitioned tables
There are two types of partition index scans. Ordered and unordered.
Ordered scan is used in common cases, including when the partitioned
table is the first in the join order and when ORDER BY ... DESC.
Whereas unordered scan is used when the partitioned table is not the
first in the join order, or in mrr when mrr_mode does not have
HA_MRR_SORTED. It can be unclear whether ordered or unordered scan has
been used. Therefore in this patch we add a field
"partitions_index_scan_method" to ANALYZE FORMAT=JSON to reveal with
method has been used. Possible values include
"merge_ordered_scans" (for ordered scan)
"iterate_over_partitions" (for unordered scan) and "both" (when both
have been used).
2026-02-03 14:55:48 +02:00
Oleksandr Byelkin
c976b527db Merge branch '11.8' into bb-12.1-release 2025-10-08 09:05:38 +02:00
Aleksey Midenkov
ff33f49d9a Merge 11.4 into 11.8 2025-09-29 18:25:09 +03:00
Marko Mäkelä
e8ef8c0055 Merge 10.11 into 11.4 2025-09-24 13:40:09 +03:00
bsrikanth-mariadb
573d3ad1c6 MDEV-33309: for update|delete analyze format=json doesn't show r_other_time_ms
Single-table UPDATE/DELETEs only show r_total_time_ms in top-level query block.
Replace it with r_table_time_ms and r_other_time_ms.
2025-09-22 10:24:14 +05:30
Oleksandr Byelkin
f1102da37a Merge branch '11.8' into 12.0 2025-05-22 09:22:55 +02:00
Sergei Golubchik
237e24497b Merge remote-tracking branch 'github/bb-11.4-release' into bb-11.8-serg 2025-04-27 19:40:00 +02:00
bsrikanth-mariadb
b6391d4e03 MDEV-36463 Change expression_cache name to subquery_cache, and make appropriate changes to the test files 2025-04-15 14:36:02 -04:00
Vasilii Lakhin
717c12de0e Fix typos in C comments inside sql/ 2025-03-14 12:08:56 +04:00
Sergei Golubchik
ae59127158 cleanup: lex_string_set3() 2024-11-05 14:00:47 -08:00
Sergei Golubchik
32e6f8ff2e cleanup: remove unconditional #ifdef's 2024-11-05 14:00:47 -08:00
Oleksandr Byelkin
ea75a0b600 Merge branch '11.4' into 11.5 2024-08-05 17:50:18 +02:00
Oleksandr Byelkin
80abd847da Merge branch '10.11' into 11.1 2024-08-03 09:32:42 +02:00
Oleksandr Byelkin
0fe39d368a Merge branch '10.6' into 10.11 2024-07-22 15:14:50 +02:00
Yuchen Pei
f071b7620b Merge branch '10.5' into 10.6 2024-07-16 15:54:22 +08:00
Oleg Smirnov
aae3233c4f MDEV-34041 Display additional information for materialized subqueries in EXPLAIN/ANALYZE FORMAT=JSON
This commits adds the "materialization" block to the output of
EXPLAIN/ANALYZE FORMAT=JSON when materialized subqueries are involved
into processing. In the case of ANALYZE additional runtime information
is displayed, such as:
  - chosen strategy of materialization
  - number of partial match/index lookup loops
  - sizes of partial match buffers
2024-07-11 17:40:39 +07:00
Alexander Barkov
4e805aed85 Merge remote-tracking branch 'origin/11.4' into 11.5 2024-07-10 12:17:09 +04:00
Alexander Barkov
44af9bfc67 Merge remote-tracking branch 'origin/10.11' into 11.1 2024-07-09 10:45:47 +04:00
Alexander Barkov
4d71a117a3 Merge remote-tracking branch 'origin/10.6' into 10.11 2024-07-08 21:52:08 +04:00
Alexander Barkov
8f4ec79d09 Merge remote-tracking branch 'origin/11.4' into 11.5 2024-07-08 12:25:04 +04:00
Sergei Petrunia
513c827041 MDEV-34190: r_engine_stats.pages_read_count is unrealistically low
The symptoms were: take a server with no activity and a table that's
not in the buffer pool. Run a query that reads the whole table and
observe that r_engine_stats.pages_read_count shows about 2% of the table
was read. Who reads the rest?

The cause was that page prefetching done inside InnoDB was not counted.

This counts page prefetch requests made in buf_read_ahead_random() and
buf_read_ahead_linear() and makes them visible in:

- ANALYZE: r_engine_stats.pages_prefetch_read_count
- Slow Query Log: Pages_prefetched:

This patch intentionally doesn't attempt to count the time to read the
prefetched pages:
* there's no obvious place where one can do it
* prefetch reads may be done in parallel (right?), it is not clear how
  to count the time in this case.
2024-07-04 15:24:49 +03:00
Yuchen Pei
2d3e2c58b6 Merge branch '10.11' into 11.1 2024-05-31 10:54:31 +10:00
Marko Mäkelä
22ba7e4ff8 Merge 10.6 into 10.11 2024-05-30 16:04:00 +03:00
Sergei Petrunia
36ab6cc80c MDEV-34125: ANALYZE FORMAT=JSON: r_engine_stats.pages_read_time_ms has wrong scale
- Change the comments in class ha_handler_stats to say the members
  are in ticks, not milliseconds.
- In sql_explain.cc, adjust the scale to print milliseconds.
2024-05-27 15:28:57 +03:00
Dave Gosselin
a11a10191a accrue statistics to correct handler 2024-04-23 22:55:22 +03:00
Sergei Petrunia
0940a96940 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.
2024-04-23 22:55:22 +03:00
Sergei Petrunia
e87d1e391b MDEV-18478 ANALYZE for statement should show selectivity of ICP, part#1
(Based on the original patch by Jason Cu)

Part #1:
- Add ha_handler_stats::{icp_attempts,icp_match}, make
  handler_index_cond_check() increment them.
- ANALYZE FORMAT=JSON now prints r_icp_filtered based on these counters.
2024-04-23 22:55:22 +03:00
Oleksandr Byelkin
0f5613a25f Merge branch '11.0' into 11.1 2023-11-08 18:03:08 +01:00
Oleksandr Byelkin
48af85db21 Merge branch '10.11' into 11.0 2023-11-08 17:09:44 +01:00
Oleksandr Byelkin
fecd78b837 Merge branch '10.10' into 10.11 2023-11-08 16:46:47 +01:00
Oleksandr Byelkin
04d9a46c41 Merge branch '10.6' into 10.10 2023-11-08 16:23:30 +01:00
Oleksandr Byelkin
b83c379420 Merge branch '10.5' into 10.6 2023-11-08 15:57:05 +01:00
Oleksandr Byelkin
6cfd2ba397 Merge branch '10.4' into 10.5 2023-11-08 12:59:00 +01:00
Sergei Petrunia
9bf2e5e3fe MDEV-32351: Significant slowdown with outer joins: Test coverage
Make ANALYZE FORMAT=JSON print block-nl-join.r_unpack_ops when
analyze_print_r_unpack_ops debug flag is set.

Then, add a testcase.
2023-10-27 15:45:20 +02:00
Sergei Petrunia
4ed5900626 ANALYZE FORMAT=JSON: Backport block-nl-join.r_unpack_time_ms from 11.0 +fix MDEV-30830.
Also fix it to work with hashed join (MDEV-30830).

Reviewed by: Monty <monty@mariadb.org>
2023-10-27 15:45:00 +02:00
Sergei Golubchik
f031889ae4 Merge branch '11.0' into 11.1 2023-09-24 01:46:43 +02:00
Alexander Barkov
baf00fc553 Merge remote-tracking branch 'origin/10.11' into 11.0 2023-08-18 07:34:54 +04:00
Sergei Petrunia
725bd56834 Merge 10.10 into 10.11 2023-08-17 13:44:05 +03:00
Sergei Petrunia
8aaacb5509 MDEV-31432 tmp_table field accessed after free
Before this patch, the code in Item_field::print() used
this convention (described in sql_explain.h:ExplainDataStructureLifetime):

- By default, the table that Item_field refers to is accessible.
- ANALYZE and SHOW {EXPLAIN|ANALYZE} may print Items after some
  temporary tables have been dropped. They use
  QT_DONT_ACCESS_TMP_TABLES flag. When it is ON, Item_field::print
  will not access the table it refers to, if it is a temp.table

The bug was that EXPLAIN statement also may compute subqueries (depending
on subquery context and @@expensive_subquery_limit setting). After the
computation, the subquery calls JOIN::cleanup(true) which drops some of
its temporary tables. Calling Item_field::print() that refer to such table
will cause an access to free'd memory.

In this patch, we take into account that query optimization can compute
a subquery and discard its temporary tables. Item_field::print() now
assumes that any temporary table might have already been dropped.
This means QT_DONT_ACCESS_TMP_TABLES flag is not needed - we imply it is
always present.

But we also make one exception: derived tables are not freed in
JOIN::cleanup() call. They are freed later in close_thread_tables(),
at the same time when regular tables are closed.
Because of that, Item_field::print may assume that temp.tables
representing derived tables are available.

Initial patch by: Rex Jonston
Reviewed by: Monty <monty@mariadb.org>
2023-08-16 17:26:37 +03:00
Marko Mäkelä
c6ac1e39b6 Merge 11.0 into 11.1 2023-07-26 15:13:43 +03:00
Marko Mäkelä
f2b4972bd4 Merge 10.11 into 11.0 2023-07-26 15:13:06 +03:00
Marko Mäkelä
bce3ee704f Merge 10.10 into 10.11 2023-07-26 14:44:43 +03:00
Marko Mäkelä
864bbd4d09 Merge 10.6 into 10.9 2023-07-26 13:42:23 +03:00
Sergei Petrunia
6e484c3bd9 MDEV-31577: Make ANALYZE FORMAT=JSON print innodb stats
ANALYZE FORMAT=JSON output now includes table.r_engine_stats which
has the engine statistics. Only non-zero members are printed.

Internally: EXPLAIN data structures Explain_table_acccess and
Explain_update now have handler* handler_for_stats pointer.
It is used to read statistics from handler_for_stats->handler_stats.

The following applies only to 10.9+, backport doesn't use it:

Explain data structures exist after the tables are closed. We avoid
walking invalid pointers using this:
- SQL layer calls Explain_query::notify_tables_are_closed() before
  closing tables.
- After that call, printing of JSON output is disabled. Non-JSON output
  can be printed but we don't access handler_for_stats when doing that.
2023-07-21 16:50:11 +03:00