在大表上缓慢MySQL SELECT

时间:2014-08-22 10:22:05

标签: mysql sql

我有一张桌子,用于存储价格随时间变化,每15分钟约有35,000件物品,为期2周。大致相当于表格中的约3500万行。我正在尝试执行最简单的查询:

SELECT buy_price, sell_price, created_at FROM price_archive WHERE item_id = X

该查询的第一个未缓存的运行大约需要4-7秒才能返回~1300行(每个项目)。对于数据库如此微不足道的事情来说,这看起来非常缓慢,特别是考虑到item_id列上有索引。

该表每15分钟插入35k行,并且每天运行任务以从<中删除项目。 (2周 - 1)之前(以阻止桌子增长太多)。我怀疑这会对表格进行相当多的碎片化,但这种碎片会导致查询执行得如此糟糕吗?如果是,那么在created_at上进行分区以删除旧数据会使其更好吗?

1306 rows in set (8.32 sec)

mysql> explain select * from price_archives where item_id = 743;
+----+-------------+----------------+------+---------------------------------+---------------------------------+---------+-------+------+-------------+
| id | select_type | table          | type | possible_keys                   | key                             | key_len | ref   | rows | Extra       |
+----+-------------+----------------+------+---------------------------------+---------------------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | price_archives | ref  | index_price_archives_on_item_id | index_price_archives_on_item_id | 5       | const | 1305 | Using where |
+----+-------------+----------------+------+---------------------------------+---------------------------------+---------+-------+------+-------------+

2 个答案:

答案 0 :(得分:1)

这是您的查询:

SELECT buy_price, sell_price, created_at
FROM price_archive
WHERE item_id = X;

此查询的最佳索引是复合索引:price_archive(item_id, buy_price, sell_price, created_at)。这是一个"覆盖"可以满足查询的索引。但它有一个缺点。此索引可能会减慢您在表中执行的插入操作。每小时140k行是很多数据,但维持这个指数不应该那么糟糕。

您在数据库中面临着一个不常见的挑战。您的查询的问题是返回的1300行左右都在不同的数据页上。很可能,该表不适合您机器上的内存,因此这会导致大约1300次访问磁盘上的文件。这就解释了为什么你会看到几秒钟的滞后时间。

另一种解决方案是确保数据表本身适合内存。虽然第一个未缓存的查询将花费一些时间,但后续查询应该非常快。

答案 1 :(得分:0)

您可以向表格列添加索引。

这个问题有百万+记录,时间从50秒到10秒。

更新表的SQL查询:

ALTER TABLE price_archives ADD INDEX (item_id);
ALTER TABLE price_archives ADD INDEX (buy_price);
ALTER TABLE price_archives ADD INDEX (sell_price);
ALTER TABLE price_archives ADD INDEX (created_at);