Mysql 案例查询优化

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

有没有办法优化此查询,因为我的数据库中有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 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'