Mysql 案例查询优化
有没有办法优化此查询,因为我的数据库中有400万条应答记录,而且运行速度非常慢?试着运行一次以创建索引:Mysql 案例查询优化,mysql,optimization,case,Mysql,Optimization,Case,有没有办法优化此查询,因为我的数据库中有400万条应答记录,而且运行速度非常慢?试着运行一次以创建索引: 在答案上创建索引ix\u ca(在创建时) 这将加快您的查询速度。如果您对原因感到好奇,请参见此处: 您可以尝试添加冗余的复合索引 SELECT COUNT(CASE WHEN VALUE = 1 THEN 1 END) AS score_1, COUNT(CASE WHEN VALUE = 2 THEN 1 END) AS score_2, COUNT(CASE WHEN VA
在答案上创建索引ix\u ca(在创建时)
这将加快您的查询速度。如果您对原因感到好奇,请参见此处:
您可以尝试添加冗余的复合索引
SELECT
COUNT(CASE WHEN VALUE = 1 THEN 1 END) AS score_1,
COUNT(CASE WHEN VALUE = 2 THEN 1 END) AS score_2,
COUNT(CASE WHEN VALUE = 3 THEN 1 END) AS score_3,
COUNT(CASE WHEN VALUE = 4 THEN 1 END) AS score_4,
COUNT(CASE WHEN VALUE = 5 THEN 1 END) AS score_5,
COUNT(CASE WHEN VALUE = 6 THEN 1 END) AS score_6,
COUNT(CASE WHEN VALUE = 7 THEN 1 END) AS score_7,
COUNT(CASE WHEN VALUE = 8 THEN 1 END) AS score_8,
COUNT(CASE WHEN VALUE = 9 THEN 1 END) AS score_9,
COUNT(CASE WHEN VALUE = 10 THEN 1 END) AS score_10
FROM
`answers`
WHERE
`created_at` BETWEEN '2017-01-01 00:00:00' AND '2019-11-30 23:59:59'
在索引中使用冗余查询应该是结果,而不只是使用索引内容访问表数据希望它的速度是10倍吗?使用构建和维护“汇总表”的数据仓库技术。在本例中,汇总表可能是
create idx1 on table answers(created_at, value)
每晚汇总一天的数据,并在小计中新建10行
然后,“报告”查询变为
CREATE TABLE subtotals (
dy DATE NOT NULL,
`value` ... NOT NULL, -- TINYINT UNSIGNED ?
ct SMALLINT UNSIGNED NOT NULL, -- this is 2 bytes, max 65K; change if might be bigger
PRIMARY KEY(value, dy) -- or perhaps the opposite order
) ENGINE=InnoDB
选择
求和(当值=1时,则ct结束)作为分数_1,
求和(当值=2时,则ct结束)作为分数_2,
求和(当值=3时,则ct结束)作为分数_3,
求和(当值=4时,则ct结束)作为分数_4,
求和(当值=5时,则ct结束)作为分数_5,
求和(当值=6时,则ct结束)作为分数_6,
求和(当值=7时,则ct结束)作为分数_7,
求和(当值=8时,则ct结束)作为分数_8,
求和(当值=9时,则ct结束)作为分数_9,
总和(当值=10时,则ct结束)作为分数_10
从…起
`小计`
其中“创建于”>=“2017-01-01”
和“创建于2019-12-01”
根据您提供的信息,在小计中大约有10000行
;这比4百万行要少得多。它的运行速度可能要快10倍以上
更多讨论:什么是非常慢的?你在创建时有索引吗?我怀疑sum比count好。使用SELECT count()GROUP BY VALUE
,然后使用CASEs来透视它。这里的问题不太可能是CASE
语句。如果缺少索引,您的请求将涉及一次完整的表扫描,即400万条记录。在语句前面添加explain
,以查看执行计划。此外,结果集的数据量可能很大,因为您的查询跨越了近3年的时间。数据必须通过网络传输才能到达前端。没有任何索引可能对此查询的任何变化有帮助。此“覆盖索引”可能比表扫描速度稍快。该索引可能不会被使用——假设表中的很多数据都在该日期范围内,因此,忽略索引并简单地扫描表会更快。(在很短的时间内,该指数将大有帮助。)
SELECT
SUM(CASE WHEN VALUE = 1 THEN ct END) AS score_1,
SUM(CASE WHEN VALUE = 2 THEN ct END) AS score_2,
SUM(CASE WHEN VALUE = 3 THEN ct END) AS score_3,
SUM(CASE WHEN VALUE = 4 THEN ct END) AS score_4,
SUM(CASE WHEN VALUE = 5 THEN ct END) AS score_5,
SUM(CASE WHEN VALUE = 6 THEN ct END) AS score_6,
SUM(CASE WHEN VALUE = 7 THEN ct END) AS score_7,
SUM(CASE WHEN VALUE = 8 THEN ct END) AS score_8,
SUM(CASE WHEN VALUE = 9 THEN ct END) AS score_9,
SUM(CASE WHEN VALUE = 10 THEN ct END) AS score_10
FROM
`subtotals`
WHERE `created_at` >= '2017-01-01'
AND `created_at` < '2019-12-01'