好的,我有以下MySQL表结构:
CREATE TABLE `creditlog` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`memberId` int(10) unsigned NOT NULL,
`quantity` decimal(10,2) unsigned DEFAULT NULL,
`timeAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`reference` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `memberId` (`memberId`),
KEY `timeAdded` (`timeAdded`));
我这样查询:
SELECT SUM(quantity) FROM creditlog where timeAdded>'2016-09-01' AND timeAdded<'2016-10-01' AND memberId IN (3,6,8,9,11)
现在,我也使用use index (timeAdded)
,因为条目数量更方便。解释上述查询显示:
type -> range,
key -> timeAdded,
rows -> 921294
extra -> using where
同时,如果我使用memberId
INDEX,则会显示:
type -> range,
key -> memberId,
rows -> 1707849
extra -> using where
现在,我的问题是,可以将这两个索引组合在一起使用并减少查询的表面,因为我还需要添加更多条件(在其他列上)。
答案 0 :(得分:0)
MySQL几乎从不在单个查询中使用两个索引;这不符合成本效益。但是,复合索引通常非常有效。您需要此订单:INDEX(memberId, timeAdded)
。
以这种方式构建索引......
WHERE
测试的=
子句中的列。 (没有,在你的情况下。)IN
。<
,BETWEEN
等GROUP BY
或ORDER BY
的所有字段。 (这里不相关。)有很多例外和警告。有些是在cookbook中提供的。
(与流行的观点相反,基数在设计索引时几乎从不相关。)
这是一种比较两个索引的方法(即使是一个太小而无法获得可靠时序的表):
FLUSH STATUS;
SELECT SQL_NO_CACHE ...;
SHOW SESSION STATUS LIKE 'Handler%';
(repeat for other query/index)
较小的数字几乎总是表示更好。
“timeAdded&gt;'2016-09-01'AND timeAdded&lt;'2016-10-01'” - 不包括第一天的午夜。我推荐这种模式:
timeAdded >= '2016-09-01'
AND timeAdded < '2016-09-01' + INTERVAL 1 MONTH
这也避免了计算日期。
闻起来像是一个常见的查询?您是否考虑过构建和维护Summary tables?等效查询可能会快10倍。