如何优化SQL查询?

时间:2018-05-06 15:09:22

标签: mysql sql

我有一个问题:

SELECT * FROM `trades`
WHERE `symbol` = 'ICX/BTC' AND `timestamp` >= :since AND `timestamp` <= :until
ORDER BY `timestamp`
LIMIT 50000

需要很长时间才能执行(超过5分钟)。 我的索引是符号时间戳

如何优化此查询?

2 个答案:

答案 0 :(得分:1)

对于此查询:

SELECT t.*
FROM trades AS t
WHERE t.symbol = 'ICX/BTC' AND t.timestamp >= :since AND t.timestamp <= :until
ORDER BY t.timestamp
LIMIT 50000;

(我只是重写了一下,所以我可以更容易地遵循它)

您需要trades(symbol, timestamp)上的索引。

但是,您似乎选择了非常多的行,因此这可能仍需要很长时间。该索引应该用于WHERE子句和ORDER BY

答案 1 :(得分:0)

在您的查询中,您只从一个表中检索数据,并且您的过滤条件是......

  1. symbol

  2. 上的平等
  3. 范围从timestamp开始从低到高扫描。

  4. 因此,(正如Gordon所提到的),两列(symbol, timestamp)上的索引可以非常有效地满足您的查询,包括过滤和排序。查询计划程序将对索引执行随机访问操作,以获取正确的符号和开始时间戳,然后按顺序读取索引,直到结束时间戳。这很有效率。

    但是,你的SELECT *可能会阻碍你的表现。为什么?例如,如果您使用SELECT symbol, timestamp, cusip, name,则可以在(symbol, timestamp, cusip, name)上创建所谓的覆盖索引。在这种情况下,扫描索引将满足整个查询。这确实非常有效。

    专业提示避免使用SELECT *,无论是出于软件稳定性还是出于性能原因。

    专业提示除非您知道它们有助于特定查询,否则请勿向表中添加额外索引。 MySQL仅对查询或子查询中的每个表使用单个索引。仅timestampsymbol上的索引都不会有太大帮助:MySQL仍需检查大量行以满足您的过滤条件。