MySQL 8.0新特性之统计直方图

数据库 MySQL
MySQL8.0实现了统计直方图。利用直方图,用户可以对一张表的一列做数据分布的统计,特别是针对没有索引的字段。这可以帮助查询优化器找到更优的执行计划。

 

概览

MySQL8.0实现了统计直方图。利用直方图,用户可以对一张表的一列做数据分布的统计,特别是针对没有索引的字段。这可以帮助查询优化器找到更优的执行计划。统计直方图的主要使用场景是用来计算字段选择性,即过滤效率。

可以通过以下方式来创建或者删除直方图: 

  1. ANALYZE TABLE tbl_name UPDATE HISTOGRAM ON col_name [, col_name] WITH N BUCKETS;  
  2. ANALYZE TABLE tbl_name DROP HISTOGRAM ON col_name [, col_name]; 

buckets默认是100。统计直方图的信息存储在数据字典表"column_statistcs"中,可以通过视图information_schema.COLUMN_STATISTICS访问。直方图以灵活的JSON的格式存储。ANALYZE TABLE会基于表大小自动判断是否要进行取样操作。ANALYZE TABLE也会基于表中列的数据分布情况以及bucket的数量来决定是否要建立等宽直方图(singleton)还是等高直方图(equi-height)。

什么是直方图

数据库中,查询优化器负责将SQL转换成最有效的执行计划。有时候,查询优化器会走不到最优的执行计划,导致花费了更多不必要的时间。造成这种情况的主要原因是,查询优化器有时无法准确的知道以下几个问题的答案:

  •  每个表有多少行?
  •  每一列有多少不同的值?
  •  每一列的数据分布情况?

举例说明:一张简单的表,两个字段,一个字段是person_id,另一个字段是time_of_day,表示睡觉时间 

  1. CREATE TABLE bedtime (  
  2. person_id INT,  
  3. time_of_day TIME); 

对于time_of_day列,大部分人上床时间会在晚上11:00左右。所以下面第一个查询会比第二个查询返回更多的行数: 

  1. 1) SELECT * FROM bedtime WHERE time_of_day BETWEEN "22:00:00" AND "23:59:00"  
  2. 2) SELECT * FROM bedtime WHERE time_of_day BETWEEN "12:00:00" AND "14:00:00" 

如果没有统计数据,优化器会假设time_of_day的值是均匀分配的,即一个人的上床时间在下午3点和晚上11点的概率差不多。如何才能使查询优化器知道数据的分布情况?一个解决方法就是在列上建立统计直方图。

直方图能近似获得一列的数据分布情况,从而让数据库知道它含有哪些数据。直方图有多种形式,MySQL支持了两种:等宽直方图(singleton)、等高直方图(equi-height)。直方图的共同点是,它们都将数据分到了一系列的buckets中去。MySQL会自动将数据划到不同的buckets中,也会自动决定创建哪种类型的直方图。

如何创建和删除统计直方图

为了管理统计直方图,ANALYZE TABLE命令新增了两个子句: 

  1. ANALYZE TABLE tbl_name UPDATE HISTOGRAM ON col_name [, col_name] WITH N BUCKETS;  
  2. ANALYZE TABLE tbl_name DROP HISTOGRAM ON col_name [, col_name]; 

第一个表示一次可以为一个或多个列创建统计直方图: 

  1. mysql> ANALYZE TABLE payment UPDATE HISTOGRAM ON amount WITH 32 BUCKETS;  
  2. +----------------+-----------+----------+---------------------------------------------------+  
  3. | Table          | Op        | Msg_type | Msg_text                                         |  
  4. +----------------+-----------+----------+---------------------------------------------------+  
  5. | sakila.payment | histogram | status   | Histogram statistics created for column 'amount'. |  
  6. +----------------+-----------+----------+---------------------------------------------------+  
  7. 1 row in set (0.27 sec)  
  8. mysql> ANALYZE TABLE payment UPDATE HISTOGRAM ON amount, payment_date WITH 32 BUCKETS;  
  9. +----------------+-----------+----------+---------------------------------------------------------+  
  10. | Table          | Op        | Msg_type | Msg_text                                                |  
  11. +----------------+-----------+----------+---------------------------------------------------------+  
  12. | sakila.payment | histogram | status   | Histogram statistics created for column 'amount'.       |  
  13. | sakila.payment | histogram | status   | Histogram statistics created for column 'payment_date'. |  
  14. +----------------+-----------+----------+---------------------------------------------------------+ 

buckets的值必须指定,可以设置为1到1024,默认值是100。 

对于不同的数据集合,buckets的值取决于以下几个因素:

  •  这列有多少不同的值
  •  数据的分布情况
  •  需要多高的准确性

但是,某些buckets的值能提升的关于数据分布情况的准确性相当低。所以,建议的做法是,开始的时候将buckets的值设的低一点,比如32,然后如果没有满足期望,再往上增大。

上面这个例子中,我们对于amount列建立了两次直方图。第一个语句,建立了一个新的直方图;第二个语句,amount列的直方图被重写了。

如果需要删除已经创建的直方图,用DROP HISTOGRAM就可以实现: 

  1. mysql> ANALYZE TABLE payment DROP HISTOGRAM ON payment_date;  
  2. +----------------+-----------+----------+---------------------------------------------------------+  
  3. | Table          | Op        | Msg_type | Msg_text                                                |  
  4. +----------------+-----------+----------+---------------------------------------------------------+  
  5. | sakila.payment | histogram | status   | Histogram statistics removed for column 'payment_date'. |  
  6. +----------------+-----------+----------+---------------------------------------------------------+ 

UPDATE HISTOGRAM可以一次性为多个列创建直方图。如果命令中间写错,ANALYZE TABLE仍然会起作用。比如,你指定了三列,但第二列不存在。MySQL仍然会为第一列和第三列创建直方图。 

  1. mysql> ANALYZE TABLE customer UPDATE HISTOGRAM ON c_birth_day, c_foobar, c_birth_month WITH 32 BUCKETS;  
  2. +----------------+-----------+----------+----------------------------------------------------------+  
  3. | Table          | Op        | Msg_type | Msg_text                                                 |  
  4. +----------------+-----------+----------+----------------------------------------------------------+  
  5. | tpcds.customer | histogram | status   | Histogram statistics created for column 'c_birth_day'.   |  
  6. | tpcds.customer | histogram | status   | Histogram statistics created for column 'c_birth_month'. |  
  7. | tpcds.customer | histogram | Error    | The column 'c_foobar' does not exist.                    | 
  8. +----------------+-----------+----------+----------------------------------------------------------+  
  9. 3 rows in set (0.15 sec) 

数据库内部发生了什么

当你读过MySQL手册,你可能已经注意到新的系统变量histogram_generation_max_mem_size。当用户建立统计直方图,这个值是用来控制大约多少内存能允许被使用。那么,为什么要控制这个呢?

当你在建立直方图的时候,MySQL server会将所有数据读到内存中,然后在内存中进行操作,包括排序。如果对一个很大的表建立直方图,可能会有风险将几百M的数据都读到内存中,但这是不明智的。为了规避这个风险,MySQL会根据给定的histogram_generation_max_mem_size的值计算该将多少行数据读到内存中。如果根据当前histogram_generation_max_mem_size的限制,MySQL认为只能读一部分数据,那么MySQL会进行取样。通过“sampling-rate”属性,可以观察到取样比率。 

  1. mysql> SET histogram_generation_max_mem_size = 1000000 
  2. Query OK, 0 rows affected (0.00 sec)  
  3. mysql> ANALYZE TABLE customer UPDATE HISTOGRAM ON c_birth_country WITH 16 BUCKETS;  
  4. +----------------+-----------+----------+------------------------------------------------------------+  
  5. | Table | Op | Msg_type | Msg_text |  
  6. +----------------+-----------+----------+------------------------------------------------------------+  
  7. | tpcds.customer | histogram | status | Histogram statistics created for column 'c_birth_country'. |  
  8. +----------------+-----------+----------+------------------------------------------------------------+  
  9. 1 row in set (0.22 sec)  
  10. mysql> SELECT histogram->>'$."sampling-rate"'  
  11. -> FROM information_schema.column_statistics  
  12. -> WHERE table_name = "customer"  
  13. -> AND column_name = "c_birth_country" 
  14. +---------------------------------+  
  15. | histogram->>'$."sampling-rate"' |  
  16. +---------------------------------+  
  17. | 0.048743243211626014 |  
  18. +---------------------------------+  
  19. 1 row in set (0.00 sec) 

优化器创建了一个直方图,大约读了c_birth_country列4.8%的数据。取样是不确定的,因此意义不大。同样的数据,同样的两条语句‘‘ANALYZE TABLE tbl UPDATE HISTOGRAM …’’,如果用了取样,得到的直方图可能就不一样。

查询案例

统计直方图可以带来些什么?我们可以看个例子,这个例子中用了直方图,在执行时间上会有很大的不同。

环境:   

  1. TPC-DS Benchmark with scale factor of 1  
  2.     Intel Core i7-4770  
  3.     Debian Stretch  
  4.     MySQL 8.0 RC1  
  5.     innodb_buffer_pool_size = 2G  
  6.     optimizer_switch = "condition_fanout_filter=on" 

Query 90

查询如下:上午售卖的数量与晚上售卖的数量的比率。 

  1. mysql> SELECT CAST(amc AS DECIMAL(15, 4)) / CAST(pmc AS DECIMAL(15, 4)) am_pm_ratio  
  2. -> FROM (SELECT COUNT(*) amc  
  3. ->              FROM web_sales,  
  4. ->                          household_demographics,  
  5. ->                          time_dim,  
  6. ->                          web_page  
  7. ->             WHERE ws_sold_time_sk = time_dim.t_time_sk  
  8. ->                          AND ws_ship_hdemo_sk = household_demographics.hd_demo_sk  
  9. ->                          AND ws_web_page_sk = web_page.wp_web_page_sk  
  10. ->                          AND time_dim.t_hour BETWEEN 9 AND 9 + 1  
  11. ->                          AND household_demographics.hd_dep_count = 2  
  12. ->                          AND web_page.wp_char_count BETWEEN 5000 AND 5200) at,  
  13. ->              (SELECT COUNT(*) pmc  
  14. ->               FROM web_sales,  
  15. ->                          household_demographics,  
  16. ->                          time_dim,  
  17. ->                          web_page  
  18. ->              WHERE ws_sold_time_sk = time_dim.t_time_sk  
  19. ->                            AND ws_ship_hdemo_sk = household_demographics.hd_demo_sk  
  20. ->                            AND ws_web_page_sk = web_page.wp_web_page_sk  
  21. ->                            AND time_dim.t_hour BETWEEN 15 AND 15 + 1  
  22. ->                            AND household_demographics.hd_dep_count = 2  
  23. ->                            AND web_page.wp_char_count BETWEEN 5000 AND 5200) pt  
  24. -> ORDER BY am_pm_ratio  
  25. -> LIMIT 100;  
  26. +-------------+  
  27. | am_pm_ratio |  
  28. +-------------+  
  29. | 1.27619048 |  
  30. +-------------+  
  31. 1 row in set (1.48 sec) 

可以看到,查询花费了1.5秒左右。看起来不算多,但是通过在一列上建立直方图,可以让执行速度快三倍。 

  1. mysql> ANALYZE TABLE web_page UPDATE HISTOGRAM ON wp_char_count WITH 8 BUCKETS;  
  2. +----------------+-----------+----------+----------------------------------------------------------+  
  3. | Table | Op | Msg_type | Msg_text |  
  4. +----------------+-----------+----------+----------------------------------------------------------+  
  5. | tpcds.web_page | histogram | status | Histogram statistics created for column 'wp_char_count'. |  
  6. +----------------+-----------+----------+----------------------------------------------------------+  
  7. 1 row in set (0.06 sec)  
  8. mysql> SELECT ...  
  9. +-------------+  
  10. | am_pm_ratio |  
  11. +-------------+  
  12. | 1.27619048 |  
  13. +-------------+  
  14. 1 row in set (0.50 sec) 

通过这个直方图,查询花费了0.5秒左右。原因呢?主要的原因是,查询语句中的谓词“web_page.wp_char_count BETWEEN 5000 AND 5200”。没有直方图的时候,优化器会假设web_page表中符合谓词“web_page.wp_char_count BETWEEN 5000 AND 5200”的数据占到总数据11.11%左右。但,这是错误的。用下面的查询语句,可以看到实际上满足条件的数据只有1.6%。 

  1. mysql> SELECT  
  2. -> (SELECT COUNT(*) FROM web_page WHERE web_page.wp_char_count BETWEEN 5000 AND 5200)  
  3. -> /  
  4. -> (SELECT COUNT(*) FROM web_page) AS ratio;  
  5. +--------+  
  6. | ratio |  
  7. +--------+  
  8. | 0.0167 |  
  9. +--------+  
  10. 1 row in set (0.00 sec) 

通过直方图,优化器会知道这个信息,并且更早进行表join,因此执行时间快了三倍。

Query 61

查询如下:在给定的年份和月份,有和没有广告宣传的情况下货物的售卖比率。 

  1. mysql> SELECT promotions,                                                                                                                                                                                        ->        total, 
  2.  
  3. ->        CAST(promotions AS DECIMAL(15, 4)) / CAST(total AS DECIMAL(15, 4)) * 100  
  4. -> FROM   (SELECT SUM(ss_ext_sales_price) promotions  
  5. ->         FROM   store_sales,  
  6. ->                store,  
  7. ->                promotion,  
  8. ->                date_dim,  
  9. ->                customer,  
  10. ->                customer_address,  
  11. ->                item  
  12. ->         WHERE  ss_sold_date_sk = d_date_sk  
  13. ->                AND ss_store_sk = s_store_sk  
  14. ->                AND ss_promo_sk = p_promo_sk  
  15. ->                AND ss_customer_sk = c_customer_sk  
  16. ->                AND ca_address_sk = c_current_addr_sk  
  17. ->                AND ss_item_sk = i_item_sk  
  18. ->                AND ca_gmt_offset = -5  
  19. ->                AND i_category = 'Home'  
  20. ->                AND ( p_channel_dmail = 'Y'  
  21. ->                       OR p_channel_email = 'Y'  
  22. ->                       OR p_channel_tv = 'Y' ) 
  23. ->                AND s_gmt_offset = -5  
  24. ->                AND d_year = 2000  
  25. ->                AND d_moy = 12) promotional_sales,  
  26. ->        (SELECT SUM(ss_ext_sales_price) total  
  27. ->         FROM   store_sales,  
  28. ->                store,  
  29. ->                date_dim,  
  30. ->                customer,  
  31. ->                customer_address,  
  32. ->                item  
  33. ->         WHERE  ss_sold_date_sk = d_date_sk  
  34. ->                AND ss_store_sk = s_store_sk  
  35. ->                AND ss_customer_sk = c_customer_sk  
  36. ->                AND ca_address_sk = c_current_addr_sk  
  37. ->                AND ss_item_sk = i_item_sk  
  38. ->                AND ca_gmt_offset = -5  
  39. ->                AND i_category = 'Home'  
  40. ->                AND s_gmt_offset = -5  
  41. ->                AND d_year = 2000  
  42. ->                AND d_moy = 12) all_sales  
  43. -> ORDER  BY promotions,  
  44. ->           total  
  45. -> LIMIT  100;  
  46. +------------+------------+--------------------------------------------------------------------------+  
  47. | promotions | total      | CAST(promotions AS DECIMAL(15, 4)) / CAST(total AS DECIMAL(15, 4)) * 100 |  
  48. +------------+------------+--------------------------------------------------------------------------+  
  49. | 3213210.07 | 5966836.78 |                                                              53.85114741 |  
  50. +------------+------------+--------------------------------------------------------------------------+  
  51. 1 row in set (2.78 sec) 

可以看到,查询花费了2.8秒左右。但是,查询优化器不知道s_gmt_offset列只有一个不同的值。没有统计数据的情况下,优化器会用所谓的“hard-coded guesstimates”,会假设10%的数据符合条件“ca_gmt_offset = -5“。如果在这个列上增加一个直方图,优化器会知道所有的数据都符合条件,因此会走一个更好的执行计划。 

  1. mysql> ANALYZE TABLE store UPDATE HISTOGRAM ON s_gmt_offset WITH 8 BUCKETS;  
  2. +-------------+-----------+----------+---------------------------------------------------------+  
  3. | Table       | Op        | Msg_type | Msg_text                                                |  
  4. +-------------+-----------+----------+---------------------------------------------------------+  
  5. | tpcds.store | histogram | status   | Histogram statistics created for column 's_gmt_offset'. |  
  6. +-------------+-----------+----------+---------------------------------------------------------+  
  7. 1 row in set (0.06 sec)  
  8. mysql> SELECT ...  
  9. +------------+------------+--------------------------------------------------------------------------+  
  10. | promotions | total      | CAST(promotions AS DECIMAL(15, 4)) / CAST(total AS DECIMAL(15, 4)) * 100 |  
  11. +------------+------------+--------------------------------------------------------------------------+  
  12. | 3213210.07 | 5966836.78 |                                                              53.85114741 |  
  13. +------------+------------+--------------------------------------------------------------------------+  
  14. 1 row in set (1.37 sec) 

有了直方图,查询花了不到1.4秒,差不多提升了2倍。原因是:

  •  第一个执行计划,优化器选择了第一个派生表在store表上做了全表扫描,然后对表item, store_sales, date_dim, customer,customer_address分别做了主键查找。
  •  但是,当MySQL意识到store表会比它猜测的返回更多的数据时,优化器会在item表上做全表扫描,然后对store_sales, store, date_dim, customer,customer_address 分别做主键查找。

为什么不用索引?

索引往往也能做上述工作,比如: 

  1. mysql> CREATE INDEX s_gmt_offset_idx ON store (s_gmt_offset);  
  2. Query OK, 0 rows affected (0.53 sec)  
  3. Records: 0  Duplicates: 0  Warnings: 0  
  4. mysql> SELECT ...  
  5. +------------+------------+--------------------------------------------------------------------------+  
  6. | promotions | total      | CAST(promotions AS DECIMAL(15, 4)) / CAST(total AS DECIMAL(15, 4)) * 100 |  
  7. +------------+------------+--------------------------------------------------------------------------+  
  8. | 3213210.07 | 5966836.78 |                                                              53.85114741 |  
  9. +------------+------------+--------------------------------------------------------------------------+  
  10. 1 row in set (1.41 sec) 

但是,用直方图而不是索引有以下两个原因:

  • 维护一个索引有代价。每一次的insert、update、delete都会需要更新索引,会对性能有一定的影响。而直方图一次创建永不更新,除非明确去更新它。所以不会影响insert、update、delete的性能。
  • 如果有索引,优化器用使用index dives技术来估算符合条件范围的记录数量。这种方式也是有代价的,特别是查询语句条件中有很长的IN列表。直方图相对而言代价小,因此可能更合适。

检索统计直方图

统计直方图以JSON的形式存在数据字典中。可以用内建的JSON函数built-in JSON functions从直方图获取一些信息。举例来说,如果需要知道amount列的直方图的创建或者更新时间,可以用JSON unquoting extraction operator来获取信息: 

  1. mysql> SELECT  
  2. ->   HISTOGRAM->>'$."last-updated"' AS last_updated  
  3. -> FROM INFORMATION_SCHEMA.COLUMN_STATISTICS  
  4. -> WHERE  
  5. ->   SCHEMA_NAME = "sakila"  
  6. ->   AND TABLE_NAME = "payment"  
  7. ->   AND COLUMN_NAME = "amount" 
  8. +----------------------------+  
  9. | last_updated               |  
  10. +----------------------------+  
  11. | 2017-09-15 11:54:25.000000 |  
  12. +----------------------------+ 

如果要查找实际有多少个buckets,以及用analyze table时指定了多少个buckets,可以如下: 

  1. mysql> SELECT  
  2. ->   TABLE_NAME,  
  3. ->   COLUMN_NAME,  
  4. ->   HISTOGRAM->>'$."number-of-buckets-specified"' AS num_buckets_specified,  
  5. ->   JSON_LENGTH(HISTOGRAM, '$.buckets') AS num_buckets_created  
  6. -> FROM INFORMATION_SCHEMA.COLUMN_STATISTICS  
  7. -> WHERE  
  8. ->   SCHEMA_NAME = "sakila"; 
  9. +------------+--------------+-----------------------+---------------------+  
  10. | TABLE_NAME | COLUMN_NAME  | num_buckets_specified | num_buckets_created |  
  11. +------------+--------------+-----------------------+---------------------+  
  12. | payment    | amount       | 32                    |                  19 |  
  13. | payment    | payment_date | 32                    |                  32 |  
  14. +------------+--------------+-----------------------+---------------------+ 

经测试,num_buckets_created与字段的distinct值很接近,近似相等;但是num_buckets_created不会大于num_buckets_specified。如果num_buckets_created与num_buckets_specified相等,那么存在可能,在创建直方图的时候指定的buckets不够多,那么此时可以通过增加buckets的数量,来提高直方图的准确性。 

buckets可以设置为1到1024

优化器trace

如果你想要知道直方图做了什么,最简单的方式就是看一下执行计划: 

  1. mysql> EXPLAIN SELECT * FROM customer WHERE c_birth_day BETWEEN 1 AND 10;  
  2. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  3. | id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |  
  4. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  5. |  1 | SIMPLE      | customer | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 98633 |    11.11 | Using where |  
  6. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  7. 1 row in set, 1 warning (0.00 sec)  
  8. mysql> ANALYZE TABLE customer UPDATE HISTOGRAM ON c_birth_day WITH 32 BUCKETS;  
  9. +----------------+-----------+----------+--------------------------------------------------------+  
  10. | Table          | Op        | Msg_type | Msg_text                                               |  
  11. +----------------+-----------+----------+--------------------------------------------------------+  
  12. | tpcds.customer | histogram | status   | Histogram statistics created for column 'c_birth_day'. |  
  13. +----------------+-----------+----------+--------------------------------------------------------+  
  14. 1 row in set (0.10 sec)  
  15. mysql> EXPLAIN SELECT * FROM customer WHERE c_birth_day BETWEEN 1 AND 10;  
  16. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  17. | id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |  
  18. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  19. |  1 | SIMPLE      | customer | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 98633 |    32.12 | Using where |  
  20. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  21. 1 row in set, 1 warning (0.00 sec) 

可以看到filtered列,从默认的11.11%变成了更精确的32.12%。但是,如果有多个条件,有些有直方图,有些没有,就比较难判断优化器做了什么改进: 

  1. mysql> EXPLAIN SELECT * FROM customer WHERE c_birth_day <= 20 AND c_birth_year = 1967 
  2. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  3. | id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |  
  4. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  5. |  1 | SIMPLE      | customer | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 98633 |     6.38 | Using where |  
  6. +----+-------------+----------+------------+------+---------------+------+---------+------+-------+----------+-------------+  
  7. 1 row in set, 1 warning (0.00 sec) 

如果想要知道更多关于直方图统计的细节,可以使用trace: 

  1. mysql> SET OPTIMIZER_TRACE = "enabled=on" 
  2. Query OK, 0 rows affected (0.00 sec)  
  3. mysql> SET OPTIMIZER_TRACE_MAX_MEM_SIZE = 1000000 
  4. Query OK, 0 rows affected (0.00 sec)  
  5. mysql> EXPLAIN SELECT * FROM customer WHERE c_birth_day <= 20 AND c_birth_year = 1967 
  6. mysql> SELECT JSON_EXTRACT(TRACE, "$**.filtering_effect") FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;  
  7. +----------------------------------------------------------------------------------------+  
  8. | JSON_EXTRACT(TRACE, "$**.filtering_effect")                                            |  
  9. +----------------------------------------------------------------------------------------+  
  10. | [[{"condition": "(`customer`.`c_birth_day` <= 20)", "histogram_selectivity": 0.6376}]] |  
  11. +----------------------------------------------------------------------------------------+  
  12. 1 row in set (0.00 sec) 

这里用了JSON_EXTRACT从trace里取出相关的部分。对于每个条件,直方图被使用的话,就会看到估算过的字段的选择性。在这个例子里,通过直方图,对“c_birth_day <= 20”条件,估算出63.76%的数据满足条件。事实上,与实际的数据分布情况基本一致: 

  1. mysql> SELECT  
  2. ->   (SELECT count(*) FROM customer WHERE c_birth_day <= 20)  
  3. ->   /  
  4. ->   (SELECT COUNT(*) FROM customer) AS ratio;  
  5. +--------+  
  6. | ratio  |  
  7. +--------+  
  8. | 0.6376 |  
  9. +--------+  
  10. 1 row in set (0.03 sec) 
责任编辑:庞桂玉 来源: 老叶茶馆
相关推荐

2018-05-31 12:52:01

数据库MySQL 8.0新特性

2018-05-30 08:38:24

数据库MySQL 8.0新特性

2018-06-01 15:41:21

2021-05-19 15:06:44

MySQL数据库命令

2017-11-01 15:50:38

数据库MySQL 8.0新特性

2017-01-05 20:00:49

大数据技术HPE Vertica

2020-05-14 11:19:19

降序索引子集

2018-05-15 16:33:12

数据库MySQL 8.0新特性

2019-07-19 15:53:45

MySQL 5.7MySQL 8.0MySQL

2009-01-16 10:01:57

MySQL复制特性测试

2012-08-20 11:03:42

IBMdW

2023-05-10 08:04:55

MySQL离线模式生效

2018-08-14 11:44:23

数据库MySQLMySQL 8.0

2009-08-03 18:34:43

TuplizersNHibernate

2017-01-09 16:25:55

Android Shortcuts系统

2013-05-20 10:25:45

vSphere 5.1vMotion

2020-04-13 17:17:28

MySQL8.0功能

2011-07-04 11:38:06

MySQL

2021-01-29 09:58:55

MySQL数据库

2011-03-24 09:22:36

Java 7JDBC4
点赞
收藏

51CTO技术栈公众号