我的MySQL表上有多种列索引

时间:2015-07-01 08:50:42

标签: mysql indexing

我有一个超过500万行的MySQL表(并且每天都在增长),我正在尝试根据最常见的查询来决定在此表上创建哪些索引。以下是我的表摘要:

CREATE TABLE entity (
    entityId CHAR(36) PRIMARY KEY,
    userId CHAR(36) NOT NULL,
    status TINYINT NOT NULL,
    acked BIT NOT NULL,
    createdAt BIGINT NOT NULL)

实际上,table有一些列,但我只写了查询时使用的列。以下是最常调用的查询列表。

查询1:

SELECT * FROM entity WHERE userId = 'x' AND status = y ORDER BY createdAt DESC LIMIT z

查询2:

SELECT COUNT(*) FROM entity WHERE userId = 'x' AND status = y

查询3:

SELECT * FROM entity WHERE userId = 'x' AND status = y AND acked = w ORDER BY createdAt DESC LIMIT z

查询4:

SELECT COUNT(*) FROM entity WHERE userId = 'x' AND status = y AND acked = w

查询5:

SELECT * FROM entity WHERE userId = 'x' ORDER BY createdAt DESC LIMIT z

查询6:

SELECT * FROM entity WHERE userId = 'x' AND createdAt < y ORDER BY createdAt DESC LIMIT z 

以下是索引替代方案:

Index1:(userId ASC,状态ASC,已确认ASC)

Index2:(userId ASC,created AS AS,status ASC,acked ASC)

Index3:(userId ASC,created AS ASC)

Index4:(userId ASC)

在构建索引组合后,我在查询上运行MySQL Workbench的EXPLAIN命令。以下是我的问题:

1。我仅使用Index5进行测试并执行查询5. Workbench说&#34;成本提示:中 - 部分索引扫描&#34;使用Index3时。并且仅在&#34;上显示userId;使用了关键部分&#34;。但是,当我删除index3并添加index4时,query5会显着减慢。因此,虽然很明显按顺序从其索引中获益,但由于工作台的解释报告,我感到困惑。 ORDER BY语句是否直接使用索引?

2. 如果回答问题1是“是”,我会考虑同时使用Index1和Index2来使上述所有6个查询都能够使用。你能提出任何建议吗?

1 个答案:

答案 0 :(得分:0)

我建议为设置SELECTs 的3个索引。

SELECT * FROM entity
        WHERE userId = 'x' AND status = y ORDER BY createdAt DESC LIMIT z
SELECT COUNT(*) FROM entity
        WHERE userId = 'x' AND status = y
-->     INDEX(userId, status, createdAt) -- or
        INDEX(status, userId, createdAt)

SELECT * FROM entity
             WHERE userId = 'x' AND status = y AND acked = w
             ORDER BY createdAt DESC LIMIT z
SELECT COUNT(*) FROM entity
             WHERE userId = 'x' AND status = y AND acked = w
-->          INDEX(status, userId, acked, createdAt)
-- This index won't work well on the first queries because `acked` is in the way.
-- My first index won't work well on these selects because it needs acked.
--    Again, keep createdAt last; shuffle the others in any way.

SELECT * FROM entity
         WHERE userId = 'x' ORDER BY createdAt DESC LIMIT z
SELECT * FROM entity
         WHERE userId = 'x' AND createdAt < y ORDER BY createdAt DESC LIMIT z 
-->      INDEX(userId, createdAt)

您的Index3是多余的,因为它由Index2处理。但是,Index2不是很有用,因为ORDER BY部分不是 last 。也就是说,createdAt之后的字段不会被使用。

我的cookbook blog涵盖了大部分内容。它说

  1. 处理所有&#34; =&#34; WHERE
  2. 的字段
  3. 然后又有一个破解 - ORDER BYcreatedAt < y