是什么让这个查询如此缓慢? (MySQL 5.6.36)

时间:2017-06-23 09:29:46

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

我有一个不断增加的大约800万行的数据库表,我的应用程序定期从中获取数据。但是,查询突然开始锁定整个系统。有大量的mysqld进程堵塞了所有CPU内核。

这可能是数据库不断增加的规模吗?或者下面的查询中是否存在导致其运行这么长时间的内容?例如UNIX_TIMESTAMP?这是慢查询日志的摘录。查询每分钟执行一次,查询时间总是约为7。

# Query_time: 6.839524  Lock_time: 0.000170 Rows_sent: 277  Rows_examined: 7989334
FROM (
    SELECT @row := @row + 1 AS `row`, `timestamp`, `price`
    FROM (
        SELECT @row := 0
    ) `derived_1`, `items`
    WHERE `price` IS NOT NULL
        AND `timestamp` >= UNIX_TIMESTAMP(NOW() - INTERVAL 1 DAY)
        AND `currency` = 'EUR'
        AND `type` = 'icon'
    ORDER BY `timestamp` ASC
) `derived_2`
WHERE `row` % 8 = 0;

尝试一下有点困难,因为它是一个生产环境。我也无法在我的开发环境中重现这个问题。

如果您需要任何其他信息,请告诉我们!

提前感谢一大堆!

3 个答案:

答案 0 :(得分:1)

创建索引,以便DBMS可以快速找到记录。此索引应包含WHERE子句的列,从与=进行比较的列开始。

CREATE idx ON items (type, currency, price, timestamp);

这甚至恰好是覆盖索引,即它包含您在查询中使用的所有列。所以DBMS甚至不必读取表,因为它可以从索引本身获取所有数据。

答案 1 :(得分:1)

最好的指数是:

INDEX(type, currency,  -- The two columns tested via '=' (in either order)
      timestamp,       -- then this, for a range test
      price)           -- finally, the rest of the columns used

这将是一个"覆盖"索引,因此它不必在索引BTree和数据BTree之间反弹。 (其他建议的索引会因此而变慢。)

希望这会使查询运行速度超过7秒。

每分钟运行一次"是不安全的。如果由于某种原因,一个实例在一分钟内未能完成,会发生什么?可能多次调用会相互绊倒,并且可能变得越来越慢。这个可能一直在阻塞你的经历。

为了避免这种情况,让工作连续运行 - 计算查询,然后睡觉,比如53秒。这将(基于当前时间)非常接近每分钟一次。或者它可以暂停足够的时间到达下一分钟(但不少于0秒)。

答案 2 :(得分:0)

时间戳索引应该会为您带来更好的性能。特别是,因为时间戳列的值可能分布很好。货币和类型的指数可能会进一步提升业绩。但也许你甚至都没注意到它,因为,只有几种不同的货币和数据类型(相比之下,有800万行)

CREATE INDEX idx_timestamp ON items (timestamp);

是的,这需要一些时间!

UNIX_TIMESTAMP(NOW() - INTERVAL 1 DAY)不是问题,因为它只计算一次。