
这篇主要介绍 MySQL 索引的 Cardinality 值(基数)以及索引的可选择性。
索引基数值
索引基数的含义:
由索引中唯一值计算的一个预估值。索引基数值的准确程度直接影响到 MySQL 优化器基于此索引的查询计划是否准确高效。
与索引基数值最为密切的典型场景就是:一条 SQL 在某一时刻执行比较慢,其中较为可能的原因就是当前表记录更新频繁,这条 SQL 执行计划走的索引基数值没及时更新,优化器选择走备用索引或者走全表扫描,从而非最优执行计划,最终执行结果没有达到预期,总体查询时间较慢,这时可能得手工更新索引的基数值。
索引的可选择性:
索引的可选择性好与坏,和索引基数关系非常密切。基数值越高,索引的可选择性越好;相反,基数越低,索引的可选择性越差。优化器优先使用的索引一般选择性都不差,除非没得选,才会走选择性稍差点的索引或者走全表扫描。
影响索引基数值的相关指标:
-
表的 sample page 个数, 也就是表样例数据页的个数,这个在之前表样例数据计算中详细讲过。
-
表的更新频率,一般来说,当 1/16 的数据页被更新过,就会自动更新索引基数。
-
索引列的数据分布程度,比如状态类,订单号,日期等。不同的数据分布,有不同的索引基数。
-
手动进行索引基数更新,比如 analyze table、show table status 等。
查看某个索引的基数值,有多种方式:
-
直接执行 show index from tablename。
-
查询数据字典表 information_schema.statstics。
举例
下面来举例说明索引基数在不同的数据分布场景下的变化以及对优化器的影响。
基础表结构如下:表 ytt_sample 有 7 个字段,5 个索引,其中主键的基数最大,可选择性最好,其他的索引要看数据的分布状况来定。
(localhost:mysqld.sock)|(ytt)>show create table ytt_sample\G
*************************** 1. row ***************************
Table: ytt_sample
Create Table: CREATE TABLE `ytt_sample` (
`id` int NOT NULL AUTO_INCREMENT,
`r1` int DEFAULT NULL,
`r2` int DEFAULT NULL,
`r3` int DEFAULT NULL,
`r4` int DEFAULT NULL,
`r5` tinyint DEFAULT NULL,
`r6` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_u1` (`r1`,`r2`,`r3`),
KEY `idx_r4` (`r4`),
KEY `idx_r5` (`r5`),
KEY `idx_r6` (`r6`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
这张表有 100 行记录。
(localhost:mysqld.sock)|(ytt)>select count(*) from ytt_sample;
+----------+
| count(*) |
+----------+
| 100 |
+----------+
1 row in set (0.03 sec)
检索数据字典,查看当前表索引基数排名:

本文深入探讨了MySQL中索引基数(Cardinality)的概念及其对查询性能的影响。基数是索引中唯一值的预估值,影响查询优化器的选择。较高的基数意味着更好的索引选择性。举例说明了不同数据分布下,如状态类、订单号、日期等字段的索引基数变化,以及如何根据基数调整联合索引以优化查询效率。同时,展示了SQL查询在不同过滤条件下,优化器如何基于基数选择执行计划。文章强调了索引建立应随数据分布变化而调整的重要性。
最低0.47元/天 解锁文章
397

被折叠的 条评论
为什么被折叠?



