Mysql没有利用“select * from table where(col,col)in”中的主键

时间:2011-03-09 22:28:01

标签: mysql sql performance

我正在尝试运行此查询:

select * from matrix where (id1, id2) in ((1,2), (3,5));

但它极其缓慢。 (id1,id2)是主键,所以这应该是一个快速查找。查询规划器失败了吗?

解释说:

|  1 | SIMPLE      | s1_movie | ALL  | NULL          | NULL | NULL    | NULL | 48768876 | Using where |

其中48768876是其扫描的行数。

如果我只搜索'in'中的1个项目,我在解释中得到rows = 1,这是正确的,因为它应该只是一个查找。

这是表格:

CREATE TABLE s1_movie (
   id1 INT NOT NULL,
   id2 INT NOT NULL,
   freq INT NOT NULL,
   diff FLOAT NOT NULL,
   PRIMARY KEY (id1, id2)
) ENGINE=INNODB;

我如何快速做到这一点?好像查询规划器失败了。

谢谢,

乔恩

3 个答案:

答案 0 :(得分:0)

您可以将WHERE拆分为两个单一查找部分,或者将它们组合在一起,但如果您不总是有两个选项,那么这将无法管理。

答案 1 :(得分:0)

问题在于您执行IN()语句的方式。 “IN”为“OR”语句提供了另一种语法。问题在于它强制进行全表扫描,这不允许索引完成它们的工作。

相反,将其分解为较小的SELECT语句,并使用UNION聚合结果。这将使您的索引更具相关性。

我不能完全按照你编写示例的方式来说明你在做什么,但是这样的事情:

SELECT * FROM matrix WHERE col1 = var1 AND col2 = var2
UNION
SELECT " FROM matrix WHERE col1 = var3 AND col2 = var4

答案 2 :(得分:0)

供讨论的样本

CREATE TABLE s1_movie (
   id1 INT NOT NULL,
   id2 INT NOT NULL,
   freq INT NOT NULL,
   diff FLOAT NOT NULL,
   PRIMARY KEY (id1, id2)
) ENGINE=INNODB;

insert into s1_movie select 1,2,3,4;
insert into s1_movie select 1,3,3,4;
insert into s1_movie select 1,4,3,4;
insert into s1_movie select 1,5,3,4;
insert into s1_movie select 1,6,3,4;
insert into s1_movie select 1,7,3,4;
insert into s1_movie select 1,8,3,4;
insert into s1_movie select 1,9,3,4;
insert into s1_movie select 1,0,3,4;
insert into s1_movie select 2,2,3,4;
insert into s1_movie select 2,3,3,4;

比较

explain extended
select * from s1_movie where (id1, id2) = (1,2) or (id1,id2) = (3,5);

explain extended
select * from s1_movie where (id1, id2) in ((1,2), (3,5));

元组很漂亮不是吗? MySQL处理元组很好,尽管Mark的答案猜测是问题所在。问题是IN子句。