为什么MySQL多列索引人满为患?
考虑下表:为什么MySQL多列索引人满为患?,mysql,indexing,multiple-columns,Mysql,Indexing,Multiple Columns,考虑下表: CREATE TABLE `log` ( `what` enum('add', 'edit', 'remove') CHARACTER SET ascii COLLATE ascii_bin NOT NULL, `with` int(10) unsigned NOT NULL, KEY `with_what` (`with`,`what`) ) ENGINE=InnoDB; INSERT INTO `log` (`what`, `with`) VALUES
CREATE TABLE `log`
(
`what` enum('add', 'edit', 'remove') CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
`with` int(10) unsigned NOT NULL,
KEY `with_what` (`with`,`what`)
) ENGINE=InnoDB;
INSERT INTO `log` (`what`, `with`) VALUES
('add', 1),
('edit', 1),
('add', 2),
('remove', 2);
据我所知,with_what
索引在其第一个with
级别上必须有2个唯一条目,在what
子索引中必须有3个(编辑:4)唯一条目。但是MySQL报告每个级别有4个唯一的条目。换句话说,每个级别的唯一元素数始终等于log
表中的行数
编辑:“第二级”的唯一条目数等于记录总数是可以的,但顶层不可以
EDIT2:注意到如果和列所占用的位数发生了变化,例如变为int(11)和int(10),则基数开始按预期工作。即使是解释从日志中选择的计数(与“with”不同)
也会为行显示足够的值
这是错误、功能还是我的误解?你的理解是错误的。多列键是从多个值创建的,而不是为多列创建的。MySQL报告4个唯一的条目,因为您输入了4对唯一的条目
您已经为这些列描述了单独的索引,因此
KEY `with_what` (`with`,`what`)
应该是
KEY `with` (`with`),
KEY `what` (`what`)
它应该按照您的要求工作。显示索引
显示近似的统计信息
在执行对表的查询时,会自动收集这些统计信息,此外,您还可以通过发出ANALYZE table log
来强制手动收集这些统计信息
基数列中的值不精确,在调用ANALYZE
之间可能会发生变化,即使基础表没有变化。您应该将“多列”索引视为“串联索引”,这意味着在索引中串联各个列。也就是说,每行有一个索引项,该项包含所有索引列
看看我的电子书,全面了解索引的工作原理:如果添加另一个条目('edit',1),它将报告5个唯一条目。这里有点不对劲。顺便说一句,我不需要单列索引。我的项目中的其他多列索引以正常方式运行,并且不会过多。例如,我有另一个who\u when
索引,它的第一级唯一条目数等于用户数(who
),而不是log
表中的总行数。您的其他表也在InnoDB中吗?他们有主键吗?如果我没记错的话,InnoDB将通过将主键附加到非唯一键来尝试使键唯一。@Danosure:是的,所有使用InnoDB存储的表<代码>日志
表没有主键,其他表有。奇怪的是,即使在log
表上,其他多列索引也没有这样的问题。也许有什么虫子什么的。我非常担心这个问题,因为log
table是项目中增长最快的表。建立这么大的低效索引可能不会花费太多的时间和空间。你所说的“MySQL为每个级别报告4个唯一的条目”是什么意思?您在哪里查找?@Quassnoi:显示表名中的索引
或在phpMyAdmin中查看表的结构选项卡。是否有方法查看确切的基数?我只是想知道为什么这是唯一一个基数极不准确的索引,而其他索引则完全准确。@actual:SELECT COUNT(DISTINCT column)FROM mytable