SlideShare a Scribd company logo
1 of 30
Download to read offline
Sergei Petrunia
MariaDB
ANALYZE for statements
MariaDB Fest
September 2020
MariaDB's hidden gem
Includes a comparison with
MySQL’s EXPLAIN ANALYZE
ANALYZE for statements
●
Introduced in MariaDB 10.1 (Oct, 2015)
− Got less recognition than it deserves
●
Was improved in the next MariaDB versions
− Based on experience
●
MySQL 8.0.18 (Oct, 2019) introduced EXPLAIN
ANALYZE
− Very similar feature, let’s compare.
The plan
●
ANALYZE In MariaDB
− ANALYZE
− ANALYZE FORMAT=JSON
●
EXPLAIN ANALYZE in MySQL
−Description and comparison
Background: EXPLAIN
●
Sometimes problem is apparent
●
Sometimes not
− Query plan vs reality?
− Where the time was spent?
explain select *
from lineitem, orders
where o_orderkey=l_orderkey and
o_orderdate between '1990-01-01' and '1998-12-06' and
l_extendedprice > 1000000
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+--------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+--------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278| 50.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 | 100.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+--------+-----------+
ANALYZE vs EXPLAIN
●
Optimize the query ●
Optimize the query
●
Run the query
− Collect execution statistics
− Discard query output
●
Produce EXPLAIN output
− With also execution statistics
●
Produce EXPLAIN output
ANALYZEEXPLAIN
14:40:206
Tabular ANALYZE statement
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
analyze select *
from lineitem, orders
where o_orderkey=l_orderkey and
o_orderdate between '1990-01-01' and '1998-12-06' and
l_extendedprice > 1000000
r_ is for “real”
●
r_rows – observed #rows
●
r_filtered – observed condition selectivity.
Interpreting r_rows
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
●
ALL/index
− r_rows ≈ rows
− Different in case of LIMIT or subqueries
●
range/index_merge
− Up to ~2x difference with InnoDB
− Bigger difference in edge cases (IGNORE INDEX?)
Interpreting r_rows (2)
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
For ref access
●
rows is AVG(records for a key)
●
Some discrepancy is normal
●
Big discrepancy (>10x) is worth investigating
− rows=1, r_rows >> rows ? No index statistics (ANALYZE TABLE)
− Column has lots of NULL values? (innodb_stats_method)
− Skewed data distribution?
●Complex, IGNORE INDEX.
Interpreting r_filtered
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
●
(r_)filtered is selectivity of “Using where”
●
r_filtered << 100% → reading and discarding lots of rows
− Check if conditions allow index use
●Use EXPLAIN|ANALYZE FORMAT=JSON to see the condition
− Consider adding indexes
− Don't chase r_filtered=100.00, tradeoff between reads and writes.
analyze select *
from lineitem, orders
where o_orderkey=l_orderkey and
o_orderdate between '1990-01-01' and '1998-12-06' and
l_extendedprice > 1000000
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
r_filtered and query plans
●
filtered
− Shows how many rows will be removed from consideration
− Is important for N-way join optimization
●
r_filtered ≈ filtered
− Optimizer doesn't know condition selectivity → poor plans
− Consider collecting histogram(s) on columns used by the condition
Tabular ANALYZE summary
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra |
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
|1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where|
|1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where|
+--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
●
New columns:
− r_rows
− r_filtered
●
Can check estimates vs reality
14:40:2012
ANALYZE FORMAT=JSON
EXPLAIN
FORMAT=JSON
+ ANALYZE = ANALYZE FORMAT=JSON
14:38:1213
Basics
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 190.15729,
"table": {
"table_name": "orders",
"access_type": "ALL",
"r_loops": 1,
"rows": 1492405,
"r_rows": 1500000,
"r_table_time_ms": 142.0726678,
"r_other_time_ms": 48.07306875,
"filtered": 100,
"r_filtered": 85.9236,
"attached_condition": "orders.o_totalprice > 50000"
}
}
}
●
r_rows
●
r_filtered
analyze format=json
select count(*) from orders where o_totalprice > 50000
●
r_loops – number of times the operation was executed
●
r_..._time_ms – total time spent
− r_table_time_ms – time spent reading data from the table
− r_other_time_ms – time spent checking the WHERE, making lookup key, etc
A complex query: join
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 4056.659499,
"table": {
"table_name": "orders",
"access_type": "ALL",
"possible_keys": ["PRIMARY", "i_o_orderdate"],
"r_loops": 1,
"rows": 1492405,
"r_rows": 1500000,
"r_table_time_ms": 323.3849353,
"r_other_time_ms": 118.576661,
"filtered": 49.99996567,
"r_filtered": 100,
"attached_condition": "orders.o_orderDATE between '1990-
},
"table": {
"table_name": "lineitem",
"access_type": "ref",
"possible_keys": ["i_l_orderkey", "i_l_orderkey_quantity"],
"key": "PRIMARY",
"key_length": "4",
"used_key_parts": ["l_orderkey"],
"ref": ["dbt3sf1.orders.o_orderkey"],
"r_loops": 1500000,
"rows": 2,
"r_rows": 4.00081,
"r_table_time_ms": 3454.758327,
"r_other_time_ms": 159.9274175,
"filtered": 100,
"r_filtered": 0,
"attached_condition": "lineitem.l_extendedprice > 1000000"
}
}
}
analyze format=json
select *
from
lineitem, orders
where
o_orderkey=l_orderkey and
o_orderdate between '1990-01-01'
and '1998-12-06' and
l_extendedprice > 1000000
●
For each table, check
− r_table_time_ms,
r_other_time_ms
− r_loops
●
Instantly shows the problem areas
A complex query: subquery
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 1104.099893,
"table": {
"table_name": "OT",
"access_type": "range",
"possible_keys": ["i_o_orderdate"],
"key": "i_o_orderdate",
"key_length": "4",
"used_key_parts": ["o_orderDATE"],
"r_loops": 1,
"rows": 78708,
"r_rows": 39162,
"r_table_time_ms": 63.71686522,
"r_other_time_ms": 5.819774094,
"filtered": 100,
"r_filtered": 0.002553496,
"index_condition": "OT.o_orderDATE between '1998-06-01' and '1998-12-06'",
"attached_condition": "OT.o_totalprice > 0.9 * (subquery#2)"
},
"subqueries": [
{
"expression_cache": {
"state": "disabled",
"r_loops": 200,
"r_hit_ratio": 0,
"query_block": {
"select_id": 2,
"r_loops": 39162,
"r_total_time_ms": 1032.541544,
"outer_ref_condition": "OT.o_custkey is not null",
"table": {
"table_name": "orders",
"access_type": "ref",
"possible_keys": ["i_o_custkey"],
"key": "i_o_custkey",
"key_length": "5",
"used_key_parts": ["o_custkey"],
"ref": ["dbt3sf1.OT.o_custkey"],
"r_loops": 39162,
"rows": 7,
"r_rows": 17.73660691,
"r_table_time_ms": 985.8381759,
"r_other_time_ms": 32.85006493,
"filtered": 100,
"r_filtered": 100
}
}
}}]}}
analyze format=json
select *
from orders OT
where
o_orderdate between '1998-06-01' and
'1998-12-06' and
o_totalprice >
0.9 * (select
sum(o_totalprice)
from
orders
where
o_custkey=OT.o_custkey)
●
Each subquery is a query_block
●
It has r_total_time_ms, r_loops
− time includes children’ time
●
Narrowing down problems in
complex queries is now easy!
●
Can also see subquery cache
− was used but had r_rit_ratio=0 so
it disabled itself.
Sorting
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 52.68082832,
"read_sorted_file": {
"r_rows": 50,
"filesort": {
"sort_key": "customer.c_acctbal desc",
"r_loops": 1,
"r_total_time_ms": 52.65527147,
"r_limit": 50,
"r_used_priority_queue": true,
"r_output_rows": 51,
"r_sort_mode": "sort_key,addon_fields",
"table": {
"table_name": "customer",
"access_type": "ALL",
"r_loops": 1,
"rows": 148473,
"r_rows": 150000,
"r_table_time_ms": 35.72704671,
"r_other_time_ms": 16.90903666,
"filtered": 100,
"r_filtered": 100
}
}
}
}
}
analyze format=json
select * from customer
order by c_acctbal desc limit 50
●
EXPLAIN shows “Using filesort”
− Will it really read/write files?
− Is my @@sort_buffer_size large
enough?
− Is priority queue optimization used?
Sorting (2)
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 52.68082832,
"read_sorted_file": {
"r_rows": 50,
"filesort": {
"sort_key": "customer.c_acctbal desc",
"r_loops": 1,
"r_total_time_ms": 52.65527147,
"r_limit": 50,
"r_used_priority_queue": true,
"r_output_rows": 51,
"r_sort_mode": "sort_key,addon_fields",
"table": {
"table_name": "customer",
"access_type": "ALL",
"r_loops": 1,
"rows": 148473,
"r_rows": 150000,
"r_table_time_ms": 35.72704671,
"r_other_time_ms": 16.90903666,
"filtered": 100,
"r_filtered": 100
}
}
}
}
}
analyze format=json
select * from customer
order by c_acctbal desc limit 50
analyze format=json
select * from customer
order by c_acctbal desc limit 50000
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 85.70263992,
"read_sorted_file": {
"r_rows": 50000,
"filesort": {
"sort_key": "customer.c_acctbal desc",
"r_loops": 1,
"r_total_time_ms": 79.33072276,
"r_limit": 50000,
"r_used_priority_queue": false,
"r_output_rows": 150000,
"r_sort_passes": 1,
"r_buffer_size": "2047Kb",
"r_sort_mode": "sort_key,packed_addon_fields",
"table": {
"table_name": "customer",
"access_type": "ALL",
"r_loops": 1,
"rows": 148473,
"r_rows": 150000,
"r_table_time_ms": 37.21097011,
"r_other_time_ms": 42.09169676,
"filtered": 100,
"r_filtered": 100
}
}
}
}
}
14:38:1218
ANALYZE and UPDATEs
●
ANALYZE works for any statement that supports EXPLAIN
− UPDATE, DELETE
●
DML statements will do the modifications!
− ANALYZE UPDATE ... will update
− ANALYZE DELETE ... will delete
− (PostgreSQL’s EXPLAIN ANALYZE also works like this)
●
Don’t want modifications to be made?
begin;
analyze update ...;
rollback;
Overhead of ANALYZE
●
ANALYZE data is:
− Counters (cheap, always counted)
− Time measurements (expensive. counted only if running ANALYZE)
●
Max. overhead I observed: 10%
− Artificial example constructed to maximize overhead
− Typically less
ANALYZE and slow query log
slow_query_log=ON
log_slow_verbosity=explain
...
# Time: 200817 12:12:47
# User@Host: root[root] @ localhost []
# Thread_id: 18 Schema: dbt3sf1 QC_hit: No
# Query_time: 3.948642 Lock_time: 0.000062 Rows_sent: 0 Rows_examined: 7501215
# Rows_affected: 0 Bytes_sent: 1756
#
# explain: id select_type table type possible_keys key key_len ref rows r_rows filtered
r_filtered Extra
# explain: 1 SIMPLE orders ALL PRIMARY,i_o_orderdate NULL NULL NULL 1492405 1500000.00 50.00 100.00
Using where
# explain: 1 SIMPLE lineitem ref PRIMARY,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4
dbt3sf1.orders.o_orderkey 24.00 100.00 0.00 Using where
#
SET timestamp=1597655567;
select *
...
●
log_slow_verbosity=explain shows ANALYZE output
●
Obstacles to printing JSON:
− No timing data
●
my.cnf
●
hostname-slow.log
− Keeping format compatible with pt-query-digest?
ANALYZE FORMAT=JSON Summary
●
It is EXPLAIN FORMAT=JSON with execution data
●
Use r_rows and r_filtered to check estimates vs reality
●
Use r_total_time_ms and r_loops to narrow down problems
●
Sorting, buffering, caches report r_ values about their
execution.
●
Please do attach ANALYZE FORMAT=JSON output when
asking for optimizer help or reporting an issue.
MySQL 8:
EXPLAIN ANALYZE
EXPLAIN ANALYZE in MySQL 8
●
Introduced in MySQL 8.0.18 (Oct, 2019)
●
Produces PostgreSQL-like output
− (In next slides, I will edit it for readability)
| -> Nested loop inner join (cost=642231.45 rows=1007917) (actual time=65.871..4580.448 rows=24 loops=1)
-> Filter: (orders.o_orderDATE between '1990-01-01' and '1998-12-06') (cost=151912.95 rows=743908) (actual
time=0.154..536.302 rows=1500000 loops=1)
-> Table scan on orders (cost=151912.95 rows=1487817) (actual time=0.146..407.074 rows=1500000 loops=1)
-> Filter: (lineitem.l_extendedprice > 104500) (cost=0.25 rows=1) (actual time=0.003..0.003 rows=0
loops=1500000)
-> Index lookup on lineitem using PRIMARY (l_orderkey=orders.o_orderkey) (cost=0.25 rows=4) (actual
time=0.002..0.002 rows=4 loops=1500000)
●
Reason for this: the runtime is switched to “Iterator
Interface”.
Basics
●
loops is like MariaDB’s r_loops
●
rows is number of rows in the output
●
rows after Filter / rows before it =
33705/39162=86% - this is r_filtered.
explain analyze
select * from orders
where
o_orderdate between '1998-06-01' and '1998-12-06' and
o_totalprice>50000
| -> Filter: (orders.o_totalprice > 50000) (cost=35418.86 rows=26233)
(actual time=0.607..51.881 rows=33705 loops=1)
-> Index range scan on orders using i_o_orderdate, with index
condition: (orders.o_orderDATE between '1998-06-01' and '1998-12-06')
(cost=35418.86 rows=78708)
(actual time=0.603..50.277 rows=39162 loops=1)
●
actual time shows X..Y
− X - time to get the first tuple
− Y- time to get all output
− Both are averages across all loops.
A complex query: join
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": 4056.659499,
"table": {
"table_name": "orders",
"access_type": "ALL",
"possible_keys": ["PRIMARY", "i_o_orderdate"],
"r_loops": 1,
"rows": 1492405,
"r_rows": 1500000,
"r_table_time_ms": 323.3849353,
"r_other_time_ms": 118.576661,
"filtered": 49.99996567,
"r_filtered": 100,
"attached_condition": "orders.o_orderDATE between '1990-
},
"table": {
"table_name": "lineitem",
"access_type": "ref",
"possible_keys": ["i_l_orderkey", "i_l_orderkey_quantity"
"key": "PRIMARY",
"key_length": "4",
"used_key_parts": ["l_orderkey"],
"ref": ["dbt3sf1.orders.o_orderkey"],
"r_loops": 1500000,
"rows": 2,
"r_rows": 4.00081,
"r_table_time_ms": 3454.758327,
"r_other_time_ms": 159.9274175,
"filtered": 100,
"r_filtered": 0,
"attached_condition": "lineitem.l_extendedprice > 1000000
}
}
analyze format=json
select *
from
lineitem, orders
where
o_orderkey=l_orderkey and
o_orderdate between '1990-01-01'
and '1998-12-06' and
l_extendedprice > 1000000
-> Nested loop inner join (cost=642231.45 rows=1007917)
(actual time=4496.131..4496.131 rows=0 loops=1)
-> Filter: (orders.o_orderDATE between '1990-01-01' and '1998-12-06')
(cost=151912.95 rows=743908)
(actual time=0.162..534.395 rows=1500000 loops=1)
-> Table scan on orders (cost=151912.95 rows=1487817)
(actual time=0.154..402.573 rows=1500000 loops=1)
-> Filter: (lineitem.l_extendedprice > 1000000) (cost=0.25 rows=1)
(actual time=0.003..0.003 rows=0 loops=1500000)
-> Index lookup on lineitem using PRIMARY
(l_orderkey=orders.o_orderkey)
(cost=0.25 rows=4)
(actual time=0.002..0.002 rows=4 loops=1500000)
●
r_total_time_ms = actual_time.second_value * loops. Practice your arithmetics skills :-)
Sorting
explain analyze select * from customer order by c_acctbal desc limit 50
| -> Limit: 50 row(s) (actual time=55.830..55.837 rows=50 loops=1)
-> Sort: customer.c_acctbal DESC, limit input to 50 row(s) per chunk (cost=15301.60 rows=148446)
(actual time=55.830..55.835 rows=50 loops=1)
-> Table scan on customer (actual time=0.137..38.462 rows=150000 loops=1)
●
No difference
●
But look at Optimizer Trace: it does show the algorithm used:
explain analyze select * from customer order by c_acctbal desc limit 50000
| -> Limit: 50000 row(s) (actual time=101.536..106.927 rows=50000 loops=1)
-> Sort: customer.c_acctbal DESC, limit input to 50000 row(s) per chunk (cost=15301.60 rows=148446)
(actual time=101.535..105.539 rows=50000 loops=1)
-> Table scan on customer (actual time=0.147..37.550 rows=150000 loops=1)
"filesort_priority_queue_optimization": {
"limit": 50,
"chosen": true
},
"filesort_priority_queue_optimization": {
"limit": 50000
},
"filesort_execution": [
],
"filesort_summary": {
"max_rows_per_buffer": 303,
"num_rows_estimate": 1400441,
"num_rows_found": 150000,
"num_initial_chunks_spilled_to_disk": 108,
"peak_memory_used": 270336,
"sort_algorithm": "std::stable_sort",
}
Handling for UPDATE/DELETE
●
Single-table UPDATE/DELETE is not supported
mysql> explain analyze delete from orders where o_orderkey=1234;
+----------------------------------------+
| EXPLAIN |
+----------------------------------------+
| <not executable by iterator executor>
|
+----------------------------------------+
1 row in set (0.00 sec)
− The same used to be true for outer joins but was fixed
●
Multi-table UPDATE/DELETE is supported
− Unlike in MariaDB/PostgreSQL, won’t make any changes.
MySQL’s EXPLAIN ANALYZE summary
●
The syntax is EXPLAIN ANALYZE
●
Postgres-like output
●
Not all plan details are shown
− Some can be found in the Optimizer Trace
●
Not all statements are supported
●
Can have higher overhead
− Artificial “bad” example: 50% overhead (vs 10% in MariaDB)
●
Shows extra info:
− Has nodes for grouping operations (worth adding?)
− #rows output for each node (worth adding, too?)
− “Time to get the first row” (not sure if useful?)
Final conclusions
●
MariaDB has
− ANALYZE <statement>
− ANALYZE FORMAT=JSON <statement>
●
Stable feature
●
Very useful in diagnosing optimizer issues
●
MySQL has got EXPLAIN ANALYZE last year
− A similar feature
− Different interface, printed data, etc
− No obvious advantages over MariaDB’s?
14:40:2030
Thanks!

More Related Content

What's hot

9. index and index organized table
9. index and index organized table9. index and index organized table
9. index and index organized tableAmrit Kaur
 
EuroPython 2022 - Automated Refactoring Large Python Codebases
EuroPython 2022 - Automated Refactoring Large Python CodebasesEuroPython 2022 - Automated Refactoring Large Python Codebases
EuroPython 2022 - Automated Refactoring Large Python CodebasesJimmy Lai
 
Low Level CPU Performance Profiling Examples
Low Level CPU Performance Profiling ExamplesLow Level CPU Performance Profiling Examples
Low Level CPU Performance Profiling ExamplesTanel Poder
 
Indexing Strategies for Oracle Databases - Beyond the Create Index Statement
Indexing Strategies for Oracle Databases - Beyond the Create Index StatementIndexing Strategies for Oracle Databases - Beyond the Create Index Statement
Indexing Strategies for Oracle Databases - Beyond the Create Index StatementSean Scott
 
Recovery of lost or corrupted inno db tables(mysql uc 2010)
Recovery of lost or corrupted inno db tables(mysql uc 2010)Recovery of lost or corrupted inno db tables(mysql uc 2010)
Recovery of lost or corrupted inno db tables(mysql uc 2010)Aleksandr Kuzminsky
 
Oracle DB Performance Tuning Tips
Oracle DB Performance Tuning TipsOracle DB Performance Tuning Tips
Oracle DB Performance Tuning TipsAsanka Dilruk
 
MySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZEMySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZENorvald Ryeng
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Traceoysteing
 
Analyse OpenLDAP logs with ELK
Analyse OpenLDAP logs with ELKAnalyse OpenLDAP logs with ELK
Analyse OpenLDAP logs with ELKClément OUDOT
 
How to Take Advantage of Optimizer Improvements in MySQL 8.0
How to Take Advantage of Optimizer Improvements in MySQL 8.0How to Take Advantage of Optimizer Improvements in MySQL 8.0
How to Take Advantage of Optimizer Improvements in MySQL 8.0Norvald Ryeng
 
Git Tutorial I
Git Tutorial IGit Tutorial I
Git Tutorial IJim Yeh
 
XDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @CloudflareXDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @CloudflareC4Media
 
MySQL Performance Tuning: Top 10 Tips
MySQL Performance Tuning: Top 10 TipsMySQL Performance Tuning: Top 10 Tips
MySQL Performance Tuning: Top 10 TipsOSSCube
 
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorAlmost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorJean-François Gagné
 
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015Mikiya Okuno
 
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会Satoshi Yamada
 
Using histograms to get better performance
Using histograms to get better performanceUsing histograms to get better performance
Using histograms to get better performanceSergey Petrunya
 
Linux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowLinux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowAngel Boy
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain ExplainedJeremy Coates
 
MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)
MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)
MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)Jean-François Gagné
 

What's hot (20)

9. index and index organized table
9. index and index organized table9. index and index organized table
9. index and index organized table
 
EuroPython 2022 - Automated Refactoring Large Python Codebases
EuroPython 2022 - Automated Refactoring Large Python CodebasesEuroPython 2022 - Automated Refactoring Large Python Codebases
EuroPython 2022 - Automated Refactoring Large Python Codebases
 
Low Level CPU Performance Profiling Examples
Low Level CPU Performance Profiling ExamplesLow Level CPU Performance Profiling Examples
Low Level CPU Performance Profiling Examples
 
Indexing Strategies for Oracle Databases - Beyond the Create Index Statement
Indexing Strategies for Oracle Databases - Beyond the Create Index StatementIndexing Strategies for Oracle Databases - Beyond the Create Index Statement
Indexing Strategies for Oracle Databases - Beyond the Create Index Statement
 
Recovery of lost or corrupted inno db tables(mysql uc 2010)
Recovery of lost or corrupted inno db tables(mysql uc 2010)Recovery of lost or corrupted inno db tables(mysql uc 2010)
Recovery of lost or corrupted inno db tables(mysql uc 2010)
 
Oracle DB Performance Tuning Tips
Oracle DB Performance Tuning TipsOracle DB Performance Tuning Tips
Oracle DB Performance Tuning Tips
 
MySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZEMySQL 8.0 EXPLAIN ANALYZE
MySQL 8.0 EXPLAIN ANALYZE
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Trace
 
Analyse OpenLDAP logs with ELK
Analyse OpenLDAP logs with ELKAnalyse OpenLDAP logs with ELK
Analyse OpenLDAP logs with ELK
 
How to Take Advantage of Optimizer Improvements in MySQL 8.0
How to Take Advantage of Optimizer Improvements in MySQL 8.0How to Take Advantage of Optimizer Improvements in MySQL 8.0
How to Take Advantage of Optimizer Improvements in MySQL 8.0
 
Git Tutorial I
Git Tutorial IGit Tutorial I
Git Tutorial I
 
XDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @CloudflareXDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @Cloudflare
 
MySQL Performance Tuning: Top 10 Tips
MySQL Performance Tuning: Top 10 TipsMySQL Performance Tuning: Top 10 Tips
MySQL Performance Tuning: Top 10 Tips
 
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorAlmost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
 
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
What's New in MySQL 5.7 Optimizer @MySQL User Conference Tokyo 2015
 
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会
 
Using histograms to get better performance
Using histograms to get better performanceUsing histograms to get better performance
Using histograms to get better performance
 
Linux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowLinux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflow
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain Explained
 
MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)
MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)
MySQL Parallel Replication: All the 5.7 and 8.0 Details (LOGICAL_CLOCK)
 

Similar to ANALYZE for Statements - MariaDB's hidden gem

MariaDB: ANALYZE for statements (lightning talk)
MariaDB:  ANALYZE for statements (lightning talk)MariaDB:  ANALYZE for statements (lightning talk)
MariaDB: ANALYZE for statements (lightning talk)Sergey Petrunya
 
New optimizer features in MariaDB releases before 10.12
New optimizer features in MariaDB releases before 10.12New optimizer features in MariaDB releases before 10.12
New optimizer features in MariaDB releases before 10.12Sergey Petrunya
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performanceoysteing
 
Applied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System PresentationApplied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System PresentationRichard Crowley
 
Parallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQLParallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQLMydbops
 
Modern query optimisation features in MySQL 8.
Modern query optimisation features in MySQL 8.Modern query optimisation features in MySQL 8.
Modern query optimisation features in MySQL 8.Mydbops
 
Need for Speed: MySQL Indexing
Need for Speed: MySQL IndexingNeed for Speed: MySQL Indexing
Need for Speed: MySQL IndexingMYXPLAIN
 
How to use histograms to get better performance
How to use histograms to get better performanceHow to use histograms to get better performance
How to use histograms to get better performanceMariaDB plc
 
Optimizing queries MySQL
Optimizing queries MySQLOptimizing queries MySQL
Optimizing queries MySQLGeorgi Sotirov
 
15 protips for mysql users pfz
15 protips for mysql users   pfz15 protips for mysql users   pfz
15 protips for mysql users pfzJoshua Thijssen
 
Need for Speed: Mysql indexing
Need for Speed: Mysql indexingNeed for Speed: Mysql indexing
Need for Speed: Mysql indexingFromDual GmbH
 
MySQL 5.7. Tutorial - Dutch PHP Conference 2015
MySQL 5.7. Tutorial - Dutch PHP Conference 2015MySQL 5.7. Tutorial - Dutch PHP Conference 2015
MySQL 5.7. Tutorial - Dutch PHP Conference 2015Dave Stokes
 
MySQL 5.7 Tutorial Dutch PHP Conference 2015
MySQL 5.7 Tutorial Dutch PHP Conference 2015MySQL 5.7 Tutorial Dutch PHP Conference 2015
MySQL 5.7 Tutorial Dutch PHP Conference 2015Dave Stokes
 
Analytics functions in mysql, oracle and hive
Analytics functions in mysql, oracle and hiveAnalytics functions in mysql, oracle and hive
Analytics functions in mysql, oracle and hiveAnkit Beohar
 
Functional Database Strategies
Functional Database StrategiesFunctional Database Strategies
Functional Database StrategiesJason Swartz
 

Similar to ANALYZE for Statements - MariaDB's hidden gem (20)

Explain
ExplainExplain
Explain
 
MariaDB: ANALYZE for statements (lightning talk)
MariaDB:  ANALYZE for statements (lightning talk)MariaDB:  ANALYZE for statements (lightning talk)
MariaDB: ANALYZE for statements (lightning talk)
 
New optimizer features in MariaDB releases before 10.12
New optimizer features in MariaDB releases before 10.12New optimizer features in MariaDB releases before 10.12
New optimizer features in MariaDB releases before 10.12
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performance
 
Applied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System PresentationApplied Partitioning And Scaling Your Database System Presentation
Applied Partitioning And Scaling Your Database System Presentation
 
Parallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQLParallel Query in AWS Aurora MySQL
Parallel Query in AWS Aurora MySQL
 
Modern query optimisation features in MySQL 8.
Modern query optimisation features in MySQL 8.Modern query optimisation features in MySQL 8.
Modern query optimisation features in MySQL 8.
 
Need for Speed: MySQL Indexing
Need for Speed: MySQL IndexingNeed for Speed: MySQL Indexing
Need for Speed: MySQL Indexing
 
Explain2
Explain2Explain2
Explain2
 
How to use histograms to get better performance
How to use histograms to get better performanceHow to use histograms to get better performance
How to use histograms to get better performance
 
Optimizing queries MySQL
Optimizing queries MySQLOptimizing queries MySQL
Optimizing queries MySQL
 
MySQLinsanity
MySQLinsanityMySQLinsanity
MySQLinsanity
 
15 protips for mysql users pfz
15 protips for mysql users   pfz15 protips for mysql users   pfz
15 protips for mysql users pfz
 
Need for Speed: Mysql indexing
Need for Speed: Mysql indexingNeed for Speed: Mysql indexing
Need for Speed: Mysql indexing
 
MySQL 5.7. Tutorial - Dutch PHP Conference 2015
MySQL 5.7. Tutorial - Dutch PHP Conference 2015MySQL 5.7. Tutorial - Dutch PHP Conference 2015
MySQL 5.7. Tutorial - Dutch PHP Conference 2015
 
MySQL 5.7 Tutorial Dutch PHP Conference 2015
MySQL 5.7 Tutorial Dutch PHP Conference 2015MySQL 5.7 Tutorial Dutch PHP Conference 2015
MySQL 5.7 Tutorial Dutch PHP Conference 2015
 
Mysql 4.0 casual
Mysql 4.0 casualMysql 4.0 casual
Mysql 4.0 casual
 
Analytics functions in mysql, oracle and hive
Analytics functions in mysql, oracle and hiveAnalytics functions in mysql, oracle and hive
Analytics functions in mysql, oracle and hive
 
Pro PostgreSQL
Pro PostgreSQLPro PostgreSQL
Pro PostgreSQL
 
Functional Database Strategies
Functional Database StrategiesFunctional Database Strategies
Functional Database Strategies
 

More from Sergey Petrunya

Improved histograms in MariaDB 10.8
Improved histograms in MariaDB 10.8Improved histograms in MariaDB 10.8
Improved histograms in MariaDB 10.8Sergey Petrunya
 
Improving MariaDB’s Query Optimizer with better selectivity estimates
Improving MariaDB’s Query Optimizer with better selectivity estimatesImproving MariaDB’s Query Optimizer with better selectivity estimates
Improving MariaDB’s Query Optimizer with better selectivity estimatesSergey Petrunya
 
JSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureJSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureSergey Petrunya
 
Optimizer Trace Walkthrough
Optimizer Trace WalkthroughOptimizer Trace Walkthrough
Optimizer Trace WalkthroughSergey Petrunya
 
Optimizer features in recent releases of other databases
Optimizer features in recent releases of other databasesOptimizer features in recent releases of other databases
Optimizer features in recent releases of other databasesSergey Petrunya
 
MariaDB 10.4 - что нового
MariaDB 10.4 - что новогоMariaDB 10.4 - что нового
MariaDB 10.4 - что новогоSergey Petrunya
 
MariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit holeMariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit holeSergey Petrunya
 
Query Optimizer in MariaDB 10.4
Query Optimizer in MariaDB 10.4Query Optimizer in MariaDB 10.4
Query Optimizer in MariaDB 10.4Sergey Petrunya
 
Lessons for the optimizer from running the TPC-DS benchmark
Lessons for the optimizer from running the TPC-DS benchmarkLessons for the optimizer from running the TPC-DS benchmark
Lessons for the optimizer from running the TPC-DS benchmarkSergey Petrunya
 
MariaDB 10.3 Optimizer - where does it stand
MariaDB 10.3 Optimizer - where does it standMariaDB 10.3 Optimizer - where does it stand
MariaDB 10.3 Optimizer - where does it standSergey Petrunya
 
MyRocks in MariaDB | M18
MyRocks in MariaDB | M18MyRocks in MariaDB | M18
MyRocks in MariaDB | M18Sergey Petrunya
 
New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3Sergey Petrunya
 
Histograms in MariaDB, MySQL and PostgreSQL
Histograms in MariaDB, MySQL and PostgreSQLHistograms in MariaDB, MySQL and PostgreSQL
Histograms in MariaDB, MySQL and PostgreSQLSergey Petrunya
 
Common Table Expressions in MariaDB 10.2
Common Table Expressions in MariaDB 10.2Common Table Expressions in MariaDB 10.2
Common Table Expressions in MariaDB 10.2Sergey Petrunya
 
MyRocks in MariaDB: why and how
MyRocks in MariaDB: why and howMyRocks in MariaDB: why and how
MyRocks in MariaDB: why and howSergey Petrunya
 
Эволюция репликации в MySQL и MariaDB
Эволюция репликации в MySQL и MariaDBЭволюция репликации в MySQL и MariaDB
Эволюция репликации в MySQL и MariaDBSergey Petrunya
 
Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)
Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)
Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)Sergey Petrunya
 
MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.Sergey Petrunya
 

More from Sergey Petrunya (20)

Improved histograms in MariaDB 10.8
Improved histograms in MariaDB 10.8Improved histograms in MariaDB 10.8
Improved histograms in MariaDB 10.8
 
Improving MariaDB’s Query Optimizer with better selectivity estimates
Improving MariaDB’s Query Optimizer with better selectivity estimatesImproving MariaDB’s Query Optimizer with better selectivity estimates
Improving MariaDB’s Query Optimizer with better selectivity estimates
 
JSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureJSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger picture
 
Optimizer Trace Walkthrough
Optimizer Trace WalkthroughOptimizer Trace Walkthrough
Optimizer Trace Walkthrough
 
Optimizer features in recent releases of other databases
Optimizer features in recent releases of other databasesOptimizer features in recent releases of other databases
Optimizer features in recent releases of other databases
 
MariaDB 10.4 - что нового
MariaDB 10.4 - что новогоMariaDB 10.4 - что нового
MariaDB 10.4 - что нового
 
MariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit holeMariaDB Optimizer - further down the rabbit hole
MariaDB Optimizer - further down the rabbit hole
 
Query Optimizer in MariaDB 10.4
Query Optimizer in MariaDB 10.4Query Optimizer in MariaDB 10.4
Query Optimizer in MariaDB 10.4
 
Lessons for the optimizer from running the TPC-DS benchmark
Lessons for the optimizer from running the TPC-DS benchmarkLessons for the optimizer from running the TPC-DS benchmark
Lessons for the optimizer from running the TPC-DS benchmark
 
MariaDB 10.3 Optimizer - where does it stand
MariaDB 10.3 Optimizer - where does it standMariaDB 10.3 Optimizer - where does it stand
MariaDB 10.3 Optimizer - where does it stand
 
MyRocks in MariaDB | M18
MyRocks in MariaDB | M18MyRocks in MariaDB | M18
MyRocks in MariaDB | M18
 
New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3New Query Optimizer features in MariaDB 10.3
New Query Optimizer features in MariaDB 10.3
 
MyRocks in MariaDB
MyRocks in MariaDBMyRocks in MariaDB
MyRocks in MariaDB
 
Histograms in MariaDB, MySQL and PostgreSQL
Histograms in MariaDB, MySQL and PostgreSQLHistograms in MariaDB, MySQL and PostgreSQL
Histograms in MariaDB, MySQL and PostgreSQL
 
Say Hello to MyRocks
Say Hello to MyRocksSay Hello to MyRocks
Say Hello to MyRocks
 
Common Table Expressions in MariaDB 10.2
Common Table Expressions in MariaDB 10.2Common Table Expressions in MariaDB 10.2
Common Table Expressions in MariaDB 10.2
 
MyRocks in MariaDB: why and how
MyRocks in MariaDB: why and howMyRocks in MariaDB: why and how
MyRocks in MariaDB: why and how
 
Эволюция репликации в MySQL и MariaDB
Эволюция репликации в MySQL и MariaDBЭволюция репликации в MySQL и MariaDB
Эволюция репликации в MySQL и MariaDB
 
Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)
Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)
Common Table Expressions in MariaDB 10.2 (Percona Live Amsterdam 2016)
 
MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.
 

Recently uploaded

PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 

Recently uploaded (20)

PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 

ANALYZE for Statements - MariaDB's hidden gem

  • 1. Sergei Petrunia MariaDB ANALYZE for statements MariaDB Fest September 2020 MariaDB's hidden gem Includes a comparison with MySQL’s EXPLAIN ANALYZE
  • 2. ANALYZE for statements ● Introduced in MariaDB 10.1 (Oct, 2015) − Got less recognition than it deserves ● Was improved in the next MariaDB versions − Based on experience ● MySQL 8.0.18 (Oct, 2019) introduced EXPLAIN ANALYZE − Very similar feature, let’s compare.
  • 3. The plan ● ANALYZE In MariaDB − ANALYZE − ANALYZE FORMAT=JSON ● EXPLAIN ANALYZE in MySQL −Description and comparison
  • 4. Background: EXPLAIN ● Sometimes problem is apparent ● Sometimes not − Query plan vs reality? − Where the time was spent? explain select * from lineitem, orders where o_orderkey=l_orderkey and o_orderdate between '1990-01-01' and '1998-12-06' and l_extendedprice > 1000000 +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+--------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+--------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278| 50.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 | 100.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+--------+-----------+
  • 5. ANALYZE vs EXPLAIN ● Optimize the query ● Optimize the query ● Run the query − Collect execution statistics − Discard query output ● Produce EXPLAIN output − With also execution statistics ● Produce EXPLAIN output ANALYZEEXPLAIN
  • 6. 14:40:206 Tabular ANALYZE statement +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ analyze select * from lineitem, orders where o_orderkey=l_orderkey and o_orderdate between '1990-01-01' and '1998-12-06' and l_extendedprice > 1000000 r_ is for “real” ● r_rows – observed #rows ● r_filtered – observed condition selectivity.
  • 7. Interpreting r_rows +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ ● ALL/index − r_rows ≈ rows − Different in case of LIMIT or subqueries ● range/index_merge − Up to ~2x difference with InnoDB − Bigger difference in edge cases (IGNORE INDEX?)
  • 8. Interpreting r_rows (2) +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ For ref access ● rows is AVG(records for a key) ● Some discrepancy is normal ● Big discrepancy (>10x) is worth investigating − rows=1, r_rows >> rows ? No index statistics (ANALYZE TABLE) − Column has lots of NULL values? (innodb_stats_method) − Skewed data distribution? ●Complex, IGNORE INDEX.
  • 9. Interpreting r_filtered +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ ● (r_)filtered is selectivity of “Using where” ● r_filtered << 100% → reading and discarding lots of rows − Check if conditions allow index use ●Use EXPLAIN|ANALYZE FORMAT=JSON to see the condition − Consider adding indexes − Don't chase r_filtered=100.00, tradeoff between reads and writes. analyze select * from lineitem, orders where o_orderkey=l_orderkey and o_orderdate between '1990-01-01' and '1998-12-06' and l_extendedprice > 1000000 +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+
  • 10. r_filtered and query plans ● filtered − Shows how many rows will be removed from consideration − Is important for N-way join optimization ● r_filtered ≈ filtered − Optimizer doesn't know condition selectivity → poor plans − Consider collecting histogram(s) on columns used by the condition
  • 11. Tabular ANALYZE summary +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |id|select_type|table |type|possible_keys|key |key_len|ref |rows |r_rows |filtered|r_filtered|Extra | +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ |1 |SIMPLE |orders |ALL |PRIMARY,i_...|NULL |NULL |NULL |1504278|1500000| 50.00 | 100.00 |Using where| |1 |SIMPLE |lineitem|ref |PRIMARY,i_...|PRIMARY|4 |orders.o_orderkey|2 |4.00 | 100.00 | 0.00 |Using where| +--+-----------+--------+----+-------------+-------+-------+-----------------+-------+-------+--------+----------+-----------+ ● New columns: − r_rows − r_filtered ● Can check estimates vs reality
  • 13. 14:38:1213 Basics { "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 190.15729, "table": { "table_name": "orders", "access_type": "ALL", "r_loops": 1, "rows": 1492405, "r_rows": 1500000, "r_table_time_ms": 142.0726678, "r_other_time_ms": 48.07306875, "filtered": 100, "r_filtered": 85.9236, "attached_condition": "orders.o_totalprice > 50000" } } } ● r_rows ● r_filtered analyze format=json select count(*) from orders where o_totalprice > 50000 ● r_loops – number of times the operation was executed ● r_..._time_ms – total time spent − r_table_time_ms – time spent reading data from the table − r_other_time_ms – time spent checking the WHERE, making lookup key, etc
  • 14. A complex query: join { "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 4056.659499, "table": { "table_name": "orders", "access_type": "ALL", "possible_keys": ["PRIMARY", "i_o_orderdate"], "r_loops": 1, "rows": 1492405, "r_rows": 1500000, "r_table_time_ms": 323.3849353, "r_other_time_ms": 118.576661, "filtered": 49.99996567, "r_filtered": 100, "attached_condition": "orders.o_orderDATE between '1990- }, "table": { "table_name": "lineitem", "access_type": "ref", "possible_keys": ["i_l_orderkey", "i_l_orderkey_quantity"], "key": "PRIMARY", "key_length": "4", "used_key_parts": ["l_orderkey"], "ref": ["dbt3sf1.orders.o_orderkey"], "r_loops": 1500000, "rows": 2, "r_rows": 4.00081, "r_table_time_ms": 3454.758327, "r_other_time_ms": 159.9274175, "filtered": 100, "r_filtered": 0, "attached_condition": "lineitem.l_extendedprice > 1000000" } } } analyze format=json select * from lineitem, orders where o_orderkey=l_orderkey and o_orderdate between '1990-01-01' and '1998-12-06' and l_extendedprice > 1000000 ● For each table, check − r_table_time_ms, r_other_time_ms − r_loops ● Instantly shows the problem areas
  • 15. A complex query: subquery { "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 1104.099893, "table": { "table_name": "OT", "access_type": "range", "possible_keys": ["i_o_orderdate"], "key": "i_o_orderdate", "key_length": "4", "used_key_parts": ["o_orderDATE"], "r_loops": 1, "rows": 78708, "r_rows": 39162, "r_table_time_ms": 63.71686522, "r_other_time_ms": 5.819774094, "filtered": 100, "r_filtered": 0.002553496, "index_condition": "OT.o_orderDATE between '1998-06-01' and '1998-12-06'", "attached_condition": "OT.o_totalprice > 0.9 * (subquery#2)" }, "subqueries": [ { "expression_cache": { "state": "disabled", "r_loops": 200, "r_hit_ratio": 0, "query_block": { "select_id": 2, "r_loops": 39162, "r_total_time_ms": 1032.541544, "outer_ref_condition": "OT.o_custkey is not null", "table": { "table_name": "orders", "access_type": "ref", "possible_keys": ["i_o_custkey"], "key": "i_o_custkey", "key_length": "5", "used_key_parts": ["o_custkey"], "ref": ["dbt3sf1.OT.o_custkey"], "r_loops": 39162, "rows": 7, "r_rows": 17.73660691, "r_table_time_ms": 985.8381759, "r_other_time_ms": 32.85006493, "filtered": 100, "r_filtered": 100 } } }}]}} analyze format=json select * from orders OT where o_orderdate between '1998-06-01' and '1998-12-06' and o_totalprice > 0.9 * (select sum(o_totalprice) from orders where o_custkey=OT.o_custkey) ● Each subquery is a query_block ● It has r_total_time_ms, r_loops − time includes children’ time ● Narrowing down problems in complex queries is now easy! ● Can also see subquery cache − was used but had r_rit_ratio=0 so it disabled itself.
  • 16. Sorting "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 52.68082832, "read_sorted_file": { "r_rows": 50, "filesort": { "sort_key": "customer.c_acctbal desc", "r_loops": 1, "r_total_time_ms": 52.65527147, "r_limit": 50, "r_used_priority_queue": true, "r_output_rows": 51, "r_sort_mode": "sort_key,addon_fields", "table": { "table_name": "customer", "access_type": "ALL", "r_loops": 1, "rows": 148473, "r_rows": 150000, "r_table_time_ms": 35.72704671, "r_other_time_ms": 16.90903666, "filtered": 100, "r_filtered": 100 } } } } } analyze format=json select * from customer order by c_acctbal desc limit 50 ● EXPLAIN shows “Using filesort” − Will it really read/write files? − Is my @@sort_buffer_size large enough? − Is priority queue optimization used?
  • 17. Sorting (2) "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 52.68082832, "read_sorted_file": { "r_rows": 50, "filesort": { "sort_key": "customer.c_acctbal desc", "r_loops": 1, "r_total_time_ms": 52.65527147, "r_limit": 50, "r_used_priority_queue": true, "r_output_rows": 51, "r_sort_mode": "sort_key,addon_fields", "table": { "table_name": "customer", "access_type": "ALL", "r_loops": 1, "rows": 148473, "r_rows": 150000, "r_table_time_ms": 35.72704671, "r_other_time_ms": 16.90903666, "filtered": 100, "r_filtered": 100 } } } } } analyze format=json select * from customer order by c_acctbal desc limit 50 analyze format=json select * from customer order by c_acctbal desc limit 50000 "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 85.70263992, "read_sorted_file": { "r_rows": 50000, "filesort": { "sort_key": "customer.c_acctbal desc", "r_loops": 1, "r_total_time_ms": 79.33072276, "r_limit": 50000, "r_used_priority_queue": false, "r_output_rows": 150000, "r_sort_passes": 1, "r_buffer_size": "2047Kb", "r_sort_mode": "sort_key,packed_addon_fields", "table": { "table_name": "customer", "access_type": "ALL", "r_loops": 1, "rows": 148473, "r_rows": 150000, "r_table_time_ms": 37.21097011, "r_other_time_ms": 42.09169676, "filtered": 100, "r_filtered": 100 } } } } }
  • 18. 14:38:1218 ANALYZE and UPDATEs ● ANALYZE works for any statement that supports EXPLAIN − UPDATE, DELETE ● DML statements will do the modifications! − ANALYZE UPDATE ... will update − ANALYZE DELETE ... will delete − (PostgreSQL’s EXPLAIN ANALYZE also works like this) ● Don’t want modifications to be made? begin; analyze update ...; rollback;
  • 19. Overhead of ANALYZE ● ANALYZE data is: − Counters (cheap, always counted) − Time measurements (expensive. counted only if running ANALYZE) ● Max. overhead I observed: 10% − Artificial example constructed to maximize overhead − Typically less
  • 20. ANALYZE and slow query log slow_query_log=ON log_slow_verbosity=explain ... # Time: 200817 12:12:47 # User@Host: root[root] @ localhost [] # Thread_id: 18 Schema: dbt3sf1 QC_hit: No # Query_time: 3.948642 Lock_time: 0.000062 Rows_sent: 0 Rows_examined: 7501215 # Rows_affected: 0 Bytes_sent: 1756 # # explain: id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra # explain: 1 SIMPLE orders ALL PRIMARY,i_o_orderdate NULL NULL NULL 1492405 1500000.00 50.00 100.00 Using where # explain: 1 SIMPLE lineitem ref PRIMARY,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3sf1.orders.o_orderkey 24.00 100.00 0.00 Using where # SET timestamp=1597655567; select * ... ● log_slow_verbosity=explain shows ANALYZE output ● Obstacles to printing JSON: − No timing data ● my.cnf ● hostname-slow.log − Keeping format compatible with pt-query-digest?
  • 21. ANALYZE FORMAT=JSON Summary ● It is EXPLAIN FORMAT=JSON with execution data ● Use r_rows and r_filtered to check estimates vs reality ● Use r_total_time_ms and r_loops to narrow down problems ● Sorting, buffering, caches report r_ values about their execution. ● Please do attach ANALYZE FORMAT=JSON output when asking for optimizer help or reporting an issue.
  • 23. EXPLAIN ANALYZE in MySQL 8 ● Introduced in MySQL 8.0.18 (Oct, 2019) ● Produces PostgreSQL-like output − (In next slides, I will edit it for readability) | -> Nested loop inner join (cost=642231.45 rows=1007917) (actual time=65.871..4580.448 rows=24 loops=1) -> Filter: (orders.o_orderDATE between '1990-01-01' and '1998-12-06') (cost=151912.95 rows=743908) (actual time=0.154..536.302 rows=1500000 loops=1) -> Table scan on orders (cost=151912.95 rows=1487817) (actual time=0.146..407.074 rows=1500000 loops=1) -> Filter: (lineitem.l_extendedprice > 104500) (cost=0.25 rows=1) (actual time=0.003..0.003 rows=0 loops=1500000) -> Index lookup on lineitem using PRIMARY (l_orderkey=orders.o_orderkey) (cost=0.25 rows=4) (actual time=0.002..0.002 rows=4 loops=1500000) ● Reason for this: the runtime is switched to “Iterator Interface”.
  • 24. Basics ● loops is like MariaDB’s r_loops ● rows is number of rows in the output ● rows after Filter / rows before it = 33705/39162=86% - this is r_filtered. explain analyze select * from orders where o_orderdate between '1998-06-01' and '1998-12-06' and o_totalprice>50000 | -> Filter: (orders.o_totalprice > 50000) (cost=35418.86 rows=26233) (actual time=0.607..51.881 rows=33705 loops=1) -> Index range scan on orders using i_o_orderdate, with index condition: (orders.o_orderDATE between '1998-06-01' and '1998-12-06') (cost=35418.86 rows=78708) (actual time=0.603..50.277 rows=39162 loops=1) ● actual time shows X..Y − X - time to get the first tuple − Y- time to get all output − Both are averages across all loops.
  • 25. A complex query: join "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": 4056.659499, "table": { "table_name": "orders", "access_type": "ALL", "possible_keys": ["PRIMARY", "i_o_orderdate"], "r_loops": 1, "rows": 1492405, "r_rows": 1500000, "r_table_time_ms": 323.3849353, "r_other_time_ms": 118.576661, "filtered": 49.99996567, "r_filtered": 100, "attached_condition": "orders.o_orderDATE between '1990- }, "table": { "table_name": "lineitem", "access_type": "ref", "possible_keys": ["i_l_orderkey", "i_l_orderkey_quantity" "key": "PRIMARY", "key_length": "4", "used_key_parts": ["l_orderkey"], "ref": ["dbt3sf1.orders.o_orderkey"], "r_loops": 1500000, "rows": 2, "r_rows": 4.00081, "r_table_time_ms": 3454.758327, "r_other_time_ms": 159.9274175, "filtered": 100, "r_filtered": 0, "attached_condition": "lineitem.l_extendedprice > 1000000 } } analyze format=json select * from lineitem, orders where o_orderkey=l_orderkey and o_orderdate between '1990-01-01' and '1998-12-06' and l_extendedprice > 1000000 -> Nested loop inner join (cost=642231.45 rows=1007917) (actual time=4496.131..4496.131 rows=0 loops=1) -> Filter: (orders.o_orderDATE between '1990-01-01' and '1998-12-06') (cost=151912.95 rows=743908) (actual time=0.162..534.395 rows=1500000 loops=1) -> Table scan on orders (cost=151912.95 rows=1487817) (actual time=0.154..402.573 rows=1500000 loops=1) -> Filter: (lineitem.l_extendedprice > 1000000) (cost=0.25 rows=1) (actual time=0.003..0.003 rows=0 loops=1500000) -> Index lookup on lineitem using PRIMARY (l_orderkey=orders.o_orderkey) (cost=0.25 rows=4) (actual time=0.002..0.002 rows=4 loops=1500000) ● r_total_time_ms = actual_time.second_value * loops. Practice your arithmetics skills :-)
  • 26. Sorting explain analyze select * from customer order by c_acctbal desc limit 50 | -> Limit: 50 row(s) (actual time=55.830..55.837 rows=50 loops=1) -> Sort: customer.c_acctbal DESC, limit input to 50 row(s) per chunk (cost=15301.60 rows=148446) (actual time=55.830..55.835 rows=50 loops=1) -> Table scan on customer (actual time=0.137..38.462 rows=150000 loops=1) ● No difference ● But look at Optimizer Trace: it does show the algorithm used: explain analyze select * from customer order by c_acctbal desc limit 50000 | -> Limit: 50000 row(s) (actual time=101.536..106.927 rows=50000 loops=1) -> Sort: customer.c_acctbal DESC, limit input to 50000 row(s) per chunk (cost=15301.60 rows=148446) (actual time=101.535..105.539 rows=50000 loops=1) -> Table scan on customer (actual time=0.147..37.550 rows=150000 loops=1) "filesort_priority_queue_optimization": { "limit": 50, "chosen": true }, "filesort_priority_queue_optimization": { "limit": 50000 }, "filesort_execution": [ ], "filesort_summary": { "max_rows_per_buffer": 303, "num_rows_estimate": 1400441, "num_rows_found": 150000, "num_initial_chunks_spilled_to_disk": 108, "peak_memory_used": 270336, "sort_algorithm": "std::stable_sort", }
  • 27. Handling for UPDATE/DELETE ● Single-table UPDATE/DELETE is not supported mysql> explain analyze delete from orders where o_orderkey=1234; +----------------------------------------+ | EXPLAIN | +----------------------------------------+ | <not executable by iterator executor> | +----------------------------------------+ 1 row in set (0.00 sec) − The same used to be true for outer joins but was fixed ● Multi-table UPDATE/DELETE is supported − Unlike in MariaDB/PostgreSQL, won’t make any changes.
  • 28. MySQL’s EXPLAIN ANALYZE summary ● The syntax is EXPLAIN ANALYZE ● Postgres-like output ● Not all plan details are shown − Some can be found in the Optimizer Trace ● Not all statements are supported ● Can have higher overhead − Artificial “bad” example: 50% overhead (vs 10% in MariaDB) ● Shows extra info: − Has nodes for grouping operations (worth adding?) − #rows output for each node (worth adding, too?) − “Time to get the first row” (not sure if useful?)
  • 29. Final conclusions ● MariaDB has − ANALYZE <statement> − ANALYZE FORMAT=JSON <statement> ● Stable feature ● Very useful in diagnosing optimizer issues ● MySQL has got EXPLAIN ANALYZE last year − A similar feature − Different interface, printed data, etc − No obvious advantages over MariaDB’s?