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

我有一个6列的索引。但是MySQL永远不会使用整个索引。它将只使用前缀

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要么使用相等的列,要么使用比较的列,但不能同时使用两者。