MySQL 索引基数

本文讨论了 MySQL 的索引基数以及如何使用 SHOW INDEXES 命令查看索引基数。

一个索引的基数是指这个索引的列中的唯一值的数量。它是根据统计信息生成的一个估计值,不一定是准确的。

索引的基数是 MySQL 查询优化器决定是否使用索引的一个重要依据。索引基数越高,使用索引越有效。

如果索引的基数很低,全表扫描可能比使用索引更有效。

查看索引基数

要查看索引基数,请使用 SHOW INDEXES 命令。 在 SHOW INDEXES 返回的列中, Cardinality 列中值是索引基数。它是一个整数,代表了索引列中的唯一值的数量。

我们使用 Sakila 示例数据库中的 film 表演示。

以下 SHOW INDEXES 语句返回 film 表中的索引信息:

SHOW INDEXES FROM film;
+-------+------------+-----------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name                    | Seq_in_index | Column_name          | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+-----------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| film  |          0 | PRIMARY                     |            1 | film_id              | A         |        1000 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| film  |          1 | idx_title                   |            1 | title                | A         |        1000 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| film  |          1 | idx_fk_language_id          |            1 | language_id          | A         |           1 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| film  |          1 | idx_fk_original_language_id |            1 | original_language_id | A         |           1 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+-------+------------+-----------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set (0.01 sec)

我们看到不同的索引具有不同的索引基数。

  • PRIMARY 索引列因为是主键,索引基数的数量核行数是相同的。

  • idx_title 索引的基数也是 1000。

  • idx_fk_language_id 索引的基数为 1,因为 film 表中只有 language_id1 的影片。正如我们在强制索引教程中讨论的, MySQL 查询优化器不会使用 idx_fk_language_id 索引,因为它的基数太小了。以下 EXPLAIN 语句说明了一切:

    EXPLAIN
    SELECT *
    FROM film
    WHERE language_id = 1;
    
    +----+-------------+-------+------------+------+--------------------+------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys      | key  | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+--------------------+------+---------+------+------+----------+-------------+
    |  1 | SIMPLE      | film  | NULL       | ALL  | idx_fk_language_id | NULL | NULL    | NULL | 1000 |   100.00 | Using where |
    +----+-------------+-------+------------+------+--------------------+------+---------+------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)

结论

MySQL SHOW INDEXES 语句返回的 Cardinality 列中值是索引基数。索引基数是 MySQL 查询优化器决定是否使用索引的一个重要依据。