我有一个大表(10M行),有3列:x,y,status。 我有一个关于x,y的主索引。
我要求'
SELECT * FROM table where (x,y) in (select 1234,5678)
大约需要5个小时
而请求SELECT * FROM table where (x,y) in (1234,5678)
给出的结果小于0.01s
我认为它是索引的问题,我尝试添加force index
但没有成功。
当我对两个查询运行解释时,第一个不使用索引:
EXPLAIN SELECT * FROM table where (x,y) in (select 1234,5678)
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+----------------+
| 1 | PRIMARY | table | NULL | ALL | NULL | NULL | NULL | NULL | 10794773 | 100.00 | Using where |
| 2 | SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
EXPLAIN SELECT * FROM table where (x,y) in (1234,5678)
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------------+------+----------+-------+
| 1 | SIMPLE | table | NULL | const | PRIMARY | PRIMARY | 8 | const,const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------------+------+----------+-------+
我当然希望使用第一种语法,因为真正的查询就像UPDATE table set status=123 where (x,y) IN (SELECT x,y from table2 where ... )
;
我真的不会忽视这种行为
答案 0 :(得分:0)
您不需要选择1234,5678子查询,而是使用...((1234,5678))(请注意值周围的双括号):
SELECT * FROM table where (x,y) in ((1234,5678))
如果使用in()
运算符针对常量值列表检查多个字段,则需要将值集包括在括号中:
SELECT * FROM table where (x,y) in ((1,1),(2,3),...(n,m))
上述语法将使MySQL能够将x,y
字段与常量值匹配,因此查询可以利用x,y
字段上的多列索引。
但是,对于带有子查询的update
查询,这可能无效。在这种情况下,我会用连接而不是子查询重写update
:
UPDATE table
INNER JOIN table2 on table.x=table2.x and table.y=table2.y
SET table.status=123
WHERE table2.fieldname=...
如果x,y
在两个表中都被编入索引,那么连接应该很快。此外,如果扩展table2索引以涵盖where
条件,那么这样的查询可能非常快。