这是真实桌子的再现。假设我有这段代码:
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 值,基数就会下降。哪个是首选值?
来自 MySQL 文档这里
基数是根据存储为整数的统计信息进行计算的,因此即使对于小表,该值也不一定准确
这意味着 NULL 值不会作为重复项存储在列中,这是有意义的。NULL 不是未知的值。因此没有两个 NULL 是相等的。
参考这里
编辑:这就是为什么你不能在 SQL 中比较 NULL 值,而=你总是必须使用is NULL
结论:基数 12 是正确的。
编辑:我忘记回答你的其他问题了。
这会增加索引的大小吗?答案在 MySQL 文档中
UNIQUE 索引创建一个约束,使得索引中的所有值都必须不同。如果您尝试添加键值与现有行匹配的新行,则会发生错误。此约束不适用于除 BDB 存储引擎之外的 NULL 值。对于其他引擎,UNIQUE 索引允许可以包含 NULL 的列有多个 NULL 值。如果为 UNIQUE 索引中的列指定前缀值,则列值在前缀内必须是唯一的。
一旦我使用空字符串而不是 NULL 值,基数就会下降。哪个是首选值?没有这样的首选值。如果空字符串适合您的目的,请使用它们。基数下降,因为空字符串 = 空字符串是正确的,但NULL = NULL是不正确的