优化 MySQL table 以获得更快的 ORDER BY 性能

Optimizing MySQL table for faster ORDER BY performance

我有一个 table 这个架构:

    CREATE TABLE `data_realtime` (
     `id` mediumint(9) unsigned NOT NULL AUTO_INCREMENT,
     `timestamp` int(10) NOT NULL,
     `ticker_id` smallint(5) unsigned NOT NULL,
     `price` decimal(7,2) unsigned NOT NULL,
     `volume` mediumint(9) unsigned NOT NULL,
     `bid` decimal(7,2) unsigned DEFAULT NULL,
     `bid_sz` smallint(6) unsigned DEFAULT NULL,
     `ask` decimal(7,2) unsigned DEFAULT NULL,
     `ask_sz` smallint(6) unsigned DEFAULT NULL,
     PRIMARY KEY (`id`),
     UNIQUE KEY `ticker_timestamp` (`ticker_id`,`timestamp`) USING BTREE,
     CONSTRAINT `data_realtime_ibfk_2` FOREIGN KEY (`ticker_id`) REFERENCES `tickers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB AUTO_INCREMENT=11330043 DEFAULT CHARSET=latin1

我正在尝试 运行 一个简单的查询来按时间戳对数据进行排序:

select * from data_realtime ORDER BY timestamp ASC

这需要 2.5 秒(大约 450 万行,最终会增加到大约 1200 万行)。但是如果我只是 运行

select * from data_realtime

需要 .25 秒

我有一个关于时间戳的复合索引(ticker_id),我认为这有助于解决这个问题。

如何提高订购时的性能?

谢谢。

编辑: 要添加到原始问题,我有这个查询:

SELECT data_latest.*, data_1m.timestamp timestamp_1m, data_1m.price price_1m, data_1m.volume volume_1m FROM 
    (SELECT B.* FROM 
        (SELECT ticker_id, max(timestamp) max_timestamp FROM `data_rt` GROUP BY ticker_id) 
    A 
    LEFT JOIN 
    data_rt B 
    ON 
    A.ticker_id=B.ticker_id 
    and A.max_timestamp=B.timestamp) 
data_latest 
LEFT JOIN 
data_rt data_1m 
ON 
data_latest.timestamp <= (data_1m.timestamp + (60*1) ) 
AND data_latest.timestamp > (data_1m.timestamp + 60*(1-0.5)) 
AND data_latest.timestamp>data_1m.timestamp 
AND data_latest.ticker_id=data_1m.ticker_id 
ORDER BY data_1m.timestamp ASC

在一组 1M 行上大约需要 1.3 秒。添加最后一个 ORDER BY 会大大增加时间。如果我改用 ORDER BY 时间戳,它只需要 0.05s。

使用临时列排序时我可以做些什么改进?

索引有助于加快查询速度;但仅当索引是 MySQL 将利用的索引时。复合索引,例如 (a, b) 上的索引将有助于同时涉及 ab 的查询;例如 WHERE a = N AND b = MORDER BY a, b。这样的索引甚至可以帮助仅涉及 a 的查询。基本上,任何复合索引 (a, b, .... n) 也充当索引 (a, b, .... n-1)(a, b, .... n-2)、... (a, b)(a)

但是,根据实际数据值,它们的适用性差异很大(请参阅我对问题本身的第二条评论);当不涉及较早的字段时,它们不能用于索引中的后面的字段。 IE。当查询仅涉及 b 时,不使用 (a, b)。 _(a,b,c, ...,n) 可以而且经常会用于涉及 (a,b,n) 的查询,但只能像 (a,b) 索引一样有效。