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

时间:2018-01-15 18:31:01

标签: mysql sql-order-by

我有一个包含此架构的表:

    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.5s(对于~4.5M行,最终将增加到大约12M行)。但如果我只是运行

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.05秒。

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

1 个答案:

答案 0 :(得分:1)

索引可以帮助加快查询速度;但只有当索引是MySQL将利用的索引时。复合索引(例如(ab)上的索引将有助于同时涉及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)

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