使用IN()子句优化查询

时间:2012-04-13 15:16:34

标签: mysql

阅读this wiki article,我发现如果在MySQL数据库中使用带有索引列的IN()子句,SELECT性能将被终止。我的问题是,如何重写我的查询,以便在保持其功能的同时不使用任何IN()子句?

我的查询是:

SELECT 
    `Route`.`route_id`, `Route`.`order`, `Route2`.`order` 
FROM 
    `routes` AS `Route` 
INNER JOIN 
    `routes` AS `Route2` 
ON `Route`.`route_id` = `Route2`.`route_id` 
WHERE 
    `Route`.`station_line_id` IN ([10 values]) AND 
    `Route2`.`station_line_id` IN ([10 values]) AND 
    `Route`.`order` <= `Route2`.`order` 
GROUP BY `
    `Route`.`station_line_id`, `Route2`.`station_line_id`, (`Route2`.`order` - `Route`.`order`)

我索引了所有列(route_id,station_line_id,station_id和line_id),id列是主键(表只是一次生成只读,所以不用担心索引所有内容)。 IN()子句中的[10 values]以逗号分隔,如:IN(1, 2, ..., 10)

基本上,我自己加入表路由表并将结果分组以获得所需的记录。其他连接用于检索关联数据。

在性能方面,使用InnoDB存储引擎,我在&gt; 30秒内执行类似的查询。使用MyISAM,我得到> 5秒。但我相信结果可以更快地获取。我在表中有大约450万条记录。

1 个答案:

答案 0 :(得分:1)

使用“哈希索引”,您将在这样的查询中获得最佳性能。 “标准”索引是一个B +树,它允许您在log(n)时间内查找条目,其中n是表中的行数。它们还维护排序顺序,因此您可以有效地执行... WHERE station_line_id > 14之类的查询,这就是您要在Order列上使用的内容。

但是,在您的情况下,使用IN子句,您只需要等效。在这种情况下,B +树将必须分别查找所有m个“[10个值]”,花费你m * log(n)时间,这显然需要5-30秒。

哈希索引用于在恒定的时间内(非常快)查找等效条目,这不依赖于(理论上)表中的行数 - 即使在大型表上也总是非常快。哈希索引的缺点是您不能使用它来执行<>之类的查询,但它在等同性查询中最快,就像您在{{1}中所执行的查询一样} IN中的子句。

编辑:对于MySQL而言,遗憾的是,它们不支持任何流行的数据库引擎上的HASH索引。如果你能够使用MEMORY或HEAP引擎,那么你可以使用HASH索引 - 并且拥有内存中的所有内容可能会相当提高性能。值得一试。

相关问题