我有一个超过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个查询都能够使用。你能提出任何建议吗?
答案 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涵盖了大部分内容。它说
WHERE
ORDER BY
或createdAt < y
。