优化 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
) 上的索引将有助于同时涉及 a
和 b
的查询;例如 WHERE a = N AND b = M
或 ORDER 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)
索引一样有效。
我有一个 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
) 上的索引将有助于同时涉及 a
和 b
的查询;例如 WHERE a = N AND b = M
或 ORDER 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)
索引一样有效。