Description\n-----------\n\nThe ANALYZE statement is similar to the EXPLAIN statement. ANALYZE statement will invoke the optimizer, execute the statement, and then produce EXPLAIN output instead of the result set. The EXPLAIN output will be annotated with statistics from statement execution.\n\nThis lets one check how close the optimizer's estimates about the query plan are to the reality. ANALYZE produces an overview, while the ANALYZE FORMAT=JSON command provides a more detailed view of the query plan and the query execution.\n\nThe syntax is\n\n``sql\nANALYZE explainable_statement;\n`\n\nwhere the statement is any statement for which one can run EXPLAIN.\n\nCommand Output\n\nConsider an example:\n\n`sql\nANALYZE SELECT  FROM tbl1 \nWHERE key1 \n  BETWEEN 10 AND 200 AND \n  col1 LIKE 'foo%'\\G\n`\n\n`\n*********************** 1. row ***********************\n           id: 1\n  select_type: SIMPLE\n        table: tbl1\n         type: range\npossible_keys: key1\n          key: key1\n      key_len: 5\n          ref: NULL\n         rows: 181\n       r_rows: 181\n     filtered: 100.00\n   r_filtered: 10.50\n        Extra: Using index condition; Using where\n`\n\nCompared to EXPLAIN, ANALYZE produces two extra columns:\n\n r_rows is an observation-based counterpart of the rows column. It shows how many rows were actually read from the table.\n r_filtered is an observation-based counterpart of the filtered column. It shows which fraction of rows was left after applying the WHERE condition.\n\n> These r_rows and r_filtered columns are also included in the EXPLAIN output written to the slow query log in MariaDB 10.1.0 and later. This explains why, even though they are not displayed by a standard EXPLAIN statement, some columns may appear in slow query log data.\n\nInterpreting the Output\n\nJoins\n\nLet's consider a more complicated example.\n\n`sql\nANALYZE SELECT \nFROM orders, customer \nWHERE\n  customer.c_custkey=orders.o_custkey AND\n  customer.c_acctbal < 0 AND\n  orders.o_totalprice > 2001000\n`\n\n`\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n| id | select_type | table    | type | possible_keys | key         | key_len | ref                | rows   | r_rows | filtered | r_filtered | Extra       |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n|  1 | SIMPLE      | customer | ALL  | PRIMARY,...   | NULL        | NULL    | NULL               | 149095 | 150000 |    18.08 |       9.13 | Using where |\n|  1 | SIMPLE      | orders   | ref  | i_o_custkey   | i_o_custkey | 5       | customer.c_custkey |      7 |     10 |   100.00 |      30.03 | Using where |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n`\n\nHere, one can see that\n\n For table customer, customer.rows=149095, customer.r_rows=150000. The estimate for number of rows we will read was fairly precise\n customer.filtered=18.08, customer.r_filtered=9.13. The optimizer somewhat overestimated the number of records that will match selectivity of condition attached to customer table (in general, when you have a full scan and r_filtered is less than 15%, it's time to consider adding an appropriate index).\n For table orders, orders.rows=7, orders.r_rows=10. This means that on average, there are 7 orders for a given c_custkey, but in our case there were 10, which is close to the expectation (when this number is consistently far from the expectation, it may be time to run ANALYZE TABLE, or even edit the table statistics manually to get better query plans).\n orders.filtered=100, orders.r_filtered=30.03. The optimizer didn't have any way to estimate which fraction of records will be left after it checks the condition that is attached to table orders (it's orders.o_totalprice > 200\\1000). So, it used 100%. In reality, it is 30%. 30% is typically not selective enough to warrant adding new indexes. For joins with many tables, it might be worth to collect and use column statistics for columns in question, this may help the optimizer to pick a better query plan.\n\nMeaning of NULL in r_rows and r_filtered\n\nLet's modify the previous example slightly\n\n`sql\nANALYZE SELECT  \nFROM orders, customer \nWHERE\n  customer.c_custkey=orders.o_custkey AND\n  customer.c_acctbal < -0 AND \n  customer.c_comment LIKE '%foo%' AND\n  orders.o_totalprice > 2001000;\n`\n\n`\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n| id | select_type | table    | type | possible_keys | key         | key_len | ref                | rows   | r_rows | filtered | r_filtered | Extra       |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n|  1 | SIMPLE      | customer | ALL  | PRIMARY,...   | NULL        | NULL    | NULL               | 149095 | 150000 |    18.08 |       0.00 | Using where |\n|  1 | SIMPLE      | orders   | ref  | i_o_custkey   | i_o_custkey | 5       | customer.c_custkey |      7 |   NULL |   100.00 |       NULL | Using where |\n+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+\n`\n\nThe output of orders.r_rows=NULL and orders.r_filtered=NULL shows that the table orders was never scanned. Indeed, we can also see customer.r_filtered=0.00. This shows that a part of WHERE attached to table customer was never satisfied (or, satisfied in less than 0.01% of cases).\n\nANALYZE FORMAT=JSON\n\nANALYZE FORMAT=JSON produces JSON output. It produces much more information than tabular ANALYZE.\n\nNotes\n\n ANALYZE UPDATE or ANALYZE DELETE will actually make updates/deletes (ANALYZE SELECT will perform the select operation and then discard the resultset).\n PostgreSQL has a similar command, EXPLAIN ANALYZE.\n* The EXPLAIN in the slow query log feature allows MariaDB to have ANALYZE` output of slow queries printed into the slow query log (see MDEV-6388).\n\nURL: https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/analyze-and-explain-statements/analyze-statement