Bug #43187 | SELECT ... WHERE (col1, col2) IN ((const, const)) is optimized, non-SELECT not | ||
---|---|---|---|
Submitted: | 25 Feb 2009 13:45 | Modified: | 30 Jul 2012 17:42 |
Reporter: | Axel Schwenke | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
Version: | 5.0, 5.1, 5.6 | OS: | Linux |
Assigned to: | CPU Architecture: | Any |
[25 Feb 2009 13:45]
Axel Schwenke
[25 Feb 2009 14:03]
Axel Schwenke
This is on 6.0 and proves a table scan is used: mysql>flush status; mysql>select * from t1 where (c1, c2) IN ((4, 12345)); +----+-------+ | c1 | c2 | +----+-------+ | 4 | 12345 | +----+-------+ 1 row in set (0,00 sec) mysql>show status like 'handler_%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Handler_read_key | 1 | | Handler_read_rnd_next | 0 | +----------------------------+-------+ mysql>flush status; mysql>delete from t1 where (c1, c2) IN ((4, 12345)); Query OK, 1 row affected (3,72 sec) mysql>show status like 'handler_%'; +----------------------------+----------+ | Variable_name | Value | +----------------------------+----------+ | Handler_delete | 1 | | Handler_read_key | 0 | | Handler_read_rnd_next | 10485761 | +----------------------------+----------+
[3 Mar 2009 18:18]
Valeriy Kravchuk
Bug #43334 is marked as a duplicate of this one.
[14 Oct 2011 6:51]
Valeriy Kravchuk
Bug #62731 was marked as a duplicate of this one.
[27 Feb 2012 9:20]
Axel Schwenke
In MySQL-5.6 we can now use EXPLAIN to see the fail. Create and fill tables like before. Then run this SQL: -- fetch an existing number (auto_inc not consecutive any more) select @n:=c1 from t2 where c1>12345 limit 1; -- explain and execution of select explain select * from t1 where (c1, c2) IN ((4, @n))\G select * from t1 where (c1, c2) IN ((4, @n)); -- explain and execution of delete explain delete from t1 where (c1, c2) IN ((4, @n))\G delete from t1 where (c1, c2) IN ((4, @n)); Result: mysql>select @n:=c1 from t2 where c1>12345 limit 1; +--------+ | @n:=c1 | +--------+ | 16371 | +--------+ 1 row in set (0,00 sec) mysql>explain select * from t1 where (c1, c2) IN ((4, @n))\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: const possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: const,const rows: 1 Extra: Using index 1 row in set (0,01 sec) mysql>select * from t1 where (c1, c2) IN ((4, @n)); +----+-------+ | c1 | c2 | +----+-------+ | 4 | 16371 | +----+-------+ 1 row in set (0,01 sec) mysql>explain delete from t1 where (c1, c2) IN ((4, @n))\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 type: ALL possible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 10486405 Extra: Using where 1 row in set (0,00 sec) mysql>delete from t1 where (c1, c2) IN ((4, @n)); Query OK, 1 row affected (11,81 sec)
[30 Jul 2012 17:42]
Paul DuBois
Noted in 5.6.6 changelog. Queries that used WHERE (col1, col2) IN ((const, const)) were optimized for SELECT, but not for DELETE or UPDATE.
[27 Sep 2012 16:59]
Jon Stephens
Also fixed in trunk (currently tagged 5.7.0).