MySQL NULL 值的基数

Pat*_*nge 3 mysql indexing

这是真实桌子的再现。假设我有这段代码:

CREATE TABLE `testTable` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`col` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `testTable` (col) VALUES (NULL), ('a'), (NULL), ('b'), (NULL), ('c'), (NULL), ('d'), (NULL), ('e'), (NULL), ('f');
ALTER TABLE `testTable` ADD INDEX (`col`);
OPTIMIZE TABLE `testTable`;
SHOW INDEX FROM `testTable`;
Run Code Online (Sandbox Code Playgroud)

我明白了

+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| testTable |          0 | PRIMARY  |            1 | id          | A         |          12 |     NULL | NULL   |      | BTREE      |         |               |
| testTable |          1 | col      |            1 | col         | A         |          12 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Run Code Online (Sandbox Code Playgroud)

为什么基数是col12 而不是 7?有 7 个唯一值,那么为什么所有 NULL 都单独计数呢?这会增加索引的大小吗?一旦我使用空字符串而不是 NULL 值,基数就会下降。哪个是首选值?

Shr*_*van 5

来自 MySQL 文档这里

基数是根据存储为整数的统计信息进行计算的,因此即使对于小表,该值也不一定准确

这意味着 NULL 值不会作为重复项存储在列中,这是有意义的。NULL 不是未知的值。因此没有两个 NULL 是相等的。

参考这里

编辑:这就是为什么你不能在 SQL 中比较 NULL 值,而=你总是必须使用is NULL

结论:基数 12 是正确的。

编辑:我忘记回答你的其他问题了。

这会增加索引的大小吗?答案在 MySQL 文档中

UNIQUE 索引创建一个约束,使得索引中的所有值都必须不同。如果您尝试添加键值与现有行匹配的新行,则会发生错误。此约束不适用于除 BDB 存储引擎之外的 NULL 值。对于其他引擎,UNIQUE 索引允许可以包含 NULL 的列有多个 NULL 值。如果为 UNIQUE 索引中的列指定前缀值,则列值在前缀内必须是唯一的。

一旦我使用空字符串而不是 NULL 值,基数就会下降。哪个是首选值?没有这样的首选值。如果空字符串适合您的目的,请使用它们。基数下降,因为空字符串 = 空字符串是正确的,但NULL = NULL是不正确的