繁体   English   中英

如何优化慢速MySQL查询

[英]How to optimize slow MySQL query

我有以下MySQL查询,它需要很长时间才能执行:

SELECT `market`.`name` AS `Markets`, count(*) * `clicks`.`cost` AS `Rev`
FROM `clicks`
INNER JOIN markets ON `clicks`.`market_id`= `markets`.`id`
WHERE clicks.created_date = `date1`
GROUP BY `markets`.`id`
ORDER BY `Rev` DESC

最初它非常慢,但后来我删除了冗余日期功能。 仍然需要很长时间才能执行。 有什么解决方案吗?

查询说明:我从一个表和行数中选择市场名称乘以另一个表的成本。 市场ID在第一个表“点击”中定义,我从“市场”表中获取市场名称。 我进一步按照他们的ID对市场进行分组,然后通过Rev降序排序

您的查询是功能滥用MySQL 部分组 您按市场进行分组,但有一个clicks.cost列的clicks.cost ,它不包含在聚合中。 无论查询速度有多快,您都会得到错误的结果。

您可以按如下方式修改查询:

SELECT market.name AS Markets, subqry.Rev FROM (
    SELECT market_id, SUM(cost) AS Rev
    FROM clicks
    WHERE created_date = 'some date'
    GROUP BY market_id
) AS subqry
INNER JOIN markets ON subqry.market_id = markets.id
ORDER BY Rev DESC

确保结果正确后,请创建以下索引:

CREATE INDEX ix_clicks ON clicks (created_date, market_id, cost)

据推测,你打算:

SELECT m.name AS Markets, SUM(c.cost) AS `Rev`
FROM clicks c INNER JOIN
     markets m
     ON c.market_id = m.id
WHERE c.created_date = ?
GROUP BY m.name
ORDER BY Rev DESC;

这对性能没有帮助。 但是, clicks(created_date, market_id, cost)索引clicks(created_date, market_id, cost)可能会为您提供所需的性能。

如果这不起作用,那么试试这个:

SELECT m.name AS Markets,
       (SELECT SUM(c.cost)
        FROM clicks c
        WHERE c.market_id = m.id AND c.created_date = ?
       ) AS `Rev`
FROM markets m
ORDER BY Rev DESC;

这将删除外部GROUP BY ,这可以获得很大的性能提升。 为此,索引应略有不同, clicks(market_id, created_date, cost)

我知道这不是问题的直接答案,如果你愿意,你可以向我投票(我理解人性,对另类思想家表现出仇恨)。


但是我要编写另外正确的方法来做这样的逻辑系统,我们每天都有大量的数据,而且我们必须在没有性能问题的情况下制作摘要报告。


不幸的是,这是时间序列数据。

它会增长并且会损失您的性能损失。

对于短期添加索引可能会解决您的问题。

但从长远来看 ,许多市场将出现,点击量将达到每天约100万 ,“索引解决方案” 并不是一个好的解决方案。

A)如果你做索引日期字段你会慢速插入。 因为它每次都会在后台执行索引更新程序。

B)如果您对分区表进行分区,那么在一段时间之后很难管理,因为拥有数百个分区是不好的,并且某些日常业务将为当前数据结构带来非常“不舒服”的任务,这将导致重新思考表模式。


解决方案是重新思考你的逻辑:

  1. 使用Kafka并将您的点击数据插入其中。
  2. 将数据插入到clicks表(表不应该有索引以快速插入)。
  3. 让工作人员从Kafka获得点击数据,做数学,并按天,周,月,年等市场创建摘要。通过创建表: clicks_by_marketsclicks_by_markets_yearlyclicks_by_markets_weeklyclicks_by_markets_daily

另一个解决方案(没有Kafka):

  1. 使用表clicks_raw来放置请求数据而不进行处理。
  2. 创建将每10分钟安排一次的脚本并处理clicks_raw表并填充表格,如: clicks_by_marketsclicks_by_markets_yearlyclicks_by_markets_weeklyclicks_by_markets_daily

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM