我有一个问题:
SELECT * FROM `trades`
WHERE `symbol` = 'ICX/BTC' AND `timestamp` >= :since AND `timestamp` <= :until
ORDER BY `timestamp`
LIMIT 50000
需要很长时间才能执行(超过5分钟)。 我的索引是符号和时间戳列
如何优化此查询?
答案 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)
在您的查询中,您只从一个表中检索数据,并且您的过滤条件是......
symbol
范围从timestamp
开始从低到高扫描。
因此,(正如Gordon所提到的),两列(symbol, timestamp)
上的索引可以非常有效地满足您的查询,包括过滤和排序。查询计划程序将对索引执行随机访问操作,以获取正确的符号和开始时间戳,然后按顺序读取索引,直到结束时间戳。这很有效率。
但是,你的SELECT *
可能会阻碍你的表现。为什么?例如,如果您使用SELECT symbol, timestamp, cusip, name
,则可以在(symbol, timestamp, cusip, name)
上创建所谓的覆盖索引。在这种情况下,扫描索引将满足整个查询。这确实非常有效。
专业提示避免使用SELECT *
,无论是出于软件稳定性还是出于性能原因。
专业提示除非您知道它们有助于特定查询,否则请勿向表中添加额外索引。 MySQL仅对查询或子查询中的每个表使用单个索引。仅timestamp
或symbol
上的索引都不会有太大帮助:MySQL仍需检查大量行以满足您的过滤条件。