MySQL性能:在大表中排序很慢,即使过滤后的子集很小

时间:2013-02-13 10:28:20

标签: mysql database-performance

我正在尝试调整我的MySQL查询,但遇到了一个我不理解的问题(因此无法修复)。从本质上讲,如果它们位于自己的表中,它可以快速排序165,000行,而不是它们是更大表的子集。

表fl6有200万行。它有一个索引x1(departure_out)。 departure_out是日期类型。

以下选项查找165,916行。需要0.1秒。

select count(*) 
from fl6 
where departure_out > "2013-04-01" 
and departure_out < "2013-04-05";

以下select具有相同的where子句,但对价格进行排序。这需要0.5秒。 0.4秒排序165,000行。

select id 
from fl6 
where departure_out > "2013-04-01" 
and departure_out < "2013-04-05"
order by price_total limit 1;

我想看看它是否会更快,所以,我创建了一个只包含165,916行的小表。然后我就这样做了。花了0.16秒。

select id 
from fl6_small
order by price_total limit 1;

因此,它可以相当快地排序165,000行,但如果它是较大表的子集,则需要两倍多的时间?我怎么做到这一点?为什么不同?

一些事情:我已经尝试在(价格)和(departure_out,价格)上设置索引。这没什么区别。无论如何,如果fl6_small中的搜索显示即使没有它也可以排序的速度,那么索引就没有必要了。

编辑:

(编辑上面的一些行数和时间以匹配用于解释计划的表)

解释计划:

+----+-------------+-------+-------+---------------+------+---------+------+--------+-----------------------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows   | Extra                       |
+----+-------------+-------+-------+---------------+------+---------+------+--------+-----------------------------+
|  1 | SIMPLE      | fl6   | range | x1            | x1   | 3       | NULL | 160493 | Using where; Using filesort |
+----+-------------+-------+-------+---------------+------+---------+------+--------+-----------------------------+

3 个答案:

答案 0 :(得分:1)

不同之处在于,在第一种情况下,MySQL将创建一个包含165000行的临时表,并在没有索引的情况下对它们进行排序。即使price列上有索引,也不能用于排序。

您的小表可能能够使用索引进行排序,因此速度更快。

答案 1 :(得分:0)

答案 2 :(得分:0)

这可能是由于一些问题造成的。

Nitpicky点 - 在大表中你做的不仅仅是一个简单的排序,你首先寻找记录,然后排序。在小表上,您没有通过depature_time搜索。但这是一个小小的作弊,因为较大的表,为了知道使用哪个n,它首先必须建立表。如果它被索引了,那么你的测试显示它不太可能显着......它仍然需要0.5秒的0.1秒。尝试小桌子上的where子句,应该花费更多的时间。如果没有,那么它指向:

其次,* 缓存未命中 *

2,000K记录可能远远超过您正在使用的计算机上的150K记录,除非您有一个专用于mysql的盒子,增加了缓存未命中的可能性。这些未命中可能是一个更大的惩罚,即使你有一个n ^ 2种或更糟的记录加载在内存和内存对齐。如果你在一个有很多ram的盒子上运行这些测试,假设其他条件相同,那么差异应该会少一些。