MYSQL查询中成千上万条记录的性能非常慢

时间:2020-02-05 12:04:46

标签: mysql sql performance mysql-slow-query-log

id    market_id      date          keyword                 sku            a             b         c  
1        1        2019-01-01    some text for this      QAB-XU-VV        3.1           2.4       3.5
2        2        2019-01-02    some text for text      ABC-XA-VV        2.1           4.1       1.2

这是表A的实例

`id` : `int primary key auto increment`
`market_id` : `int(4)`  `INDEX`
`date` : `date`   `INDEX`
`keyword`: `varchar(191)` `utf8_general_ci`
`sku`: `varchar(191)` INDEX `utf8_general_ci`
`a, b, c` : `float` 

我需要这样查询

SELECT
  sku,
  keyword,
  market_id,
  SUM(a),
  SUM(b),
  SUM(c),
FROM A
WHERE market_id = 2 AND date BETWEEN '2020-01-01' and '2020-02-02'
GROUP BY sku, keyword;

预计该查询大约有十万条记录。此查询需要5分钟以上。因此我使用了LIMITOFFSET,但没有任何改进。

请帮助我。谢谢。

已更新:

这将显示EXPLAIN个结果。 enter image description here

2 个答案:

答案 0 :(得分:4)

对于此查询:

SELECT sku, keyword, market_id,
       SUM(a), SUM(b), SUM(c)
FROM A
WHERE market_id = 2 AND
      date BETWEEN '2020-01-01' and '2020-02-02'
GROUP BY sku, keyword, market_id;

我建议在A(market_id, date, sku, keyword, a, b, c)上使用复合索引。

这是一个覆盖索引,因此不需要读取原始数据页。您也可以使用A(market_id, date)

答案 1 :(得分:1)

戈登解释了大多数事情。

请注意,GROUP BY和/或ORDER BY通常会导致流程中断,从而阻止了LIMIT的大部分收益。好吧,LIMIT实际上有一个很小的好处,但这只是传递努力和交付不同大小结果集的时间。

关于进一步改进?就目前的查询和戈登的“覆盖”索引而言,没有。

但是...如果这是一个时间序列数据,您可以每天计算SUMs的小计。然后可以更快地提取总计33天的总计;也许快十倍。

暂时汇总表将具有

PRIMARY KEY(market_id, date, sku, keyword)

sum_a, sum_b, sum_c的其他列,您将每晚在表中添加新行。

我在http://mysql.rjweb.org/doc.php/summarytables中讨论“汇总表”

有关编制索引的提示,请参见http://mysql.rjweb.org/doc.php/index_cookbook_mysql

相关问题