mysql不使用索引的所有列
我有一个6列的索引。但是MySQL永远不会使用整个索引。它将只使用前缀mysql不使用索引的所有列,mysql,Mysql,我有一个6列的索引。但是MySQL永远不会使用整个索引。它将只使用前缀 CREATE TABLE TestChannelData ( hostId MEDIUMINT UNSIGNED NOT NULL, sessionId MEDIUMINT UNSIGNED NOT NULL, sessionFragment TINYINT UNSIGNED NOT NULL, id INT UNSIGN
CREATE TABLE TestChannelData
(
hostId MEDIUMINT UNSIGNED NOT NULL,
sessionId MEDIUMINT UNSIGNED NOT NULL,
sessionFragment TINYINT UNSIGNED NOT NULL,
id INT UNSIGNED NOT NULL,
vcid INT UNSIGNED NULL,
dssId SMALLINT UNSIGNED NOT NULL
) ENGINE=InnoDB CHARSET=latin1;
CREATE TABLE TestChannelValue
(
hostId MEDIUMINT UNSIGNED NOT NULL,
sessionId MEDIUMINT UNSIGNED NOT NULL,
sessionFragment TINYINT UNSIGNED NOT NULL,
id INT UNSIGNED NOT NULL,
ertCoarse INT UNSIGNED NOT NULL,
ertFine INT UNSIGNED NOT NULL
) ENGINE=MyISAM CHARSET=latin1;
ALTER TABLE TestChannelValue
ADD KEY reverseIndex(hostId, sessionId, sessionFragment, id),
ADD KEY ertReverseIndex(ertCoarse, ertFine, hostId, sessionId, sessionFragment, id);
ALTER TABLE TestChannelValue
ADD KEY reverseErtIndex(hostId, sessionId, sessionFragment, id, ertCoarse, ertFine);
查询:
SELECT cv.sessionId, cv.hostId, cv.sessionFragment,
cd.dssId, cd.vcid,
cv.ertCoarse, cv.ertFine
FROM TestChannelData AS cd
STRAIGHT_JOIN TestChannelValue AS cv USE INDEX (ertReverseIndex)
ON ((cv.sessionId = cd.sessionId) AND
(cv.hostId = cd.hostId) AND
(cv.sessionFragment = cd.sessionFragment) AND
(cv.id = cd.id))
WHERE
(
(cv.ertCoarse > 0) AND
((cv.ertCoarse < 2000) OR ((cv.ertCoarse = 2000) AND (cv.ertFine = 0)))
)
Explain extended显示使用了indes,但key_len仅为8而不是所需的19。如果我强制索引为reverseErtIndex,则键ln为11
如果我将ert列的比较替换为正好相等,则key_len为19
为什么MySQL不使用整个索引?reverseErtIndex的11键对应于连接谓词3+3+1+4中的列。定位匹配行只需要这些列。解释输出很可能显示MySQL正在使用类型列中显示的ref-join操作 当您修改查询时,使WHERE子句中的谓词都是相等条件,那么ref join操作可以扩展到其他列,这样您就可以在EXPLAIN输出中获得更长的key_len 对于索引列上的不平等比较,MySQL不使用ref操作,但可以使用range操作。很可能,MySQL更喜欢对较短的键前缀执行ref操作,而不是对较长的键前缀执行范围操作 如果MySQL使用ertReverseIndex索引,那么基于WHERE子句中的谓词,对于范围操作,我们希望key_len为8。如果要删除ertFine列上的谓词,我们希望在解释输出中将key_len报告为4 MySQL是否正在引用,即使用索引中的任何其他列来满足查询,这将通过解释输出的额外列中是否使用索引来反映。如果存在,那么我们知道它是查询的覆盖索引,并且MySQL没有引用底层表中的块
总之,你已经得到了等式和不等式谓词的组合。MySQL可以对相等条件使用ref或equal_ref操作,但不能对不等条件使用。对于不平等,MySQL可以使用范围操作。有时MySQL会认为忽略键并进行表扫描更有效。在任何情况下,您都有点过度索引。如果一个字段包含2+个索引,那么最好只单独索引它。MySQL 5.5.15-log。用武力代替使用不会改变行为。我在一个更大的数据库上也得到了同样的结果。查询计划显示使用了该索引,但不是全部索引。双重索引只是第一次或最后一次测试,我不会在真实的数据库中使用它们。但是看起来MySQL要么使用相等的列,要么使用比较的列,但不能同时使用两者。