`

mysql compound in 查询

 
阅读更多

        mysql可以使用row constructor来做compound in 查询:select * from t where (col1,col2) in ((colt1,colt2),(colt11,colt22)).这种查询在批量查询的时候就会显得比较方便:业务上可以批量操作,提高效率。但是explain之后却发现,这种sql却使用了全表扫描。

        首先看一下mysql是怎么处理in查询的:mysql处理 in(value list)查询时会对value list做一次quick-sort,但是如果value list里的元素是tuple就无法进行排序(按哪个col排序)。bug#16081对value list中只有一个tuple情况,做了优化:将select * from t where (col1,col2) in ((colt1,colt2))转换为select * from t where col1=colt1 and col2=colt2,explain的结果也也可以看到:(count(*)是可以使用到覆盖索引的)

mysql> show create table t7\G
*************************** 1. row ***************************
       Table: t7
Create Table: CREATE TABLE `t7` (
  `a` int(11) DEFAULT NULL,
  `b` varchar(20) DEFAULT NULL,
  `c` varchar(20) DEFAULT 'ccccc',
  KEY `idx_a_b` (`a`,`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> explain select * from t7 where (a,b) in ((1,'kangaroo'),(2,'dolphin'));
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t7    | ALL  | NULL          | NULL | NULL    | NULL |   16 | Using where | 
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from t7 where (a,b) in ((1,'kangaroo'));
+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key     | key_len | ref         | rows | Extra       |
+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------------+
|  1 | SIMPLE      | t7    | ref  | idx_a_b       | idx_a_b | 68      | const,const |    4 | Using where | 
+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from t7 where a=1 and b='kangaroo';             
+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key     | key_len | ref         | rows | Extra       |
+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------------+
|  1 | SIMPLE      | t7    | ref  | idx_a_b       | idx_a_b | 68      | const,const |    4 | Using where | 
+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from t7 where (a=1 and b='kangaroo') or (a=2 and b='dolphin');
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t7    | ALL  | idx_a_b       | NULL | NULL    | NULL |   16 | Using where | 
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select count(*) from t7 where (a,b) in ((1,'kangaroo'),(2,'dolphin'));           
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | t7    | index | NULL          | idx_a_b | 68      | NULL |   16 | Using where; Using index | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

       在这种需求下,如果一定要做批量查询,那就只能改成select * from t where (col1=colt1 and col2=colt2) or (col1=colt11 and col2=colt2).

 

 

 

参考链接:

http://www.facebook.com/note.php?note_id=243134480932

http://dev.mysql.com/doc/refman/5.5/en/row-subqueries.html

http://bugs.mysql.com/bug.php?id=16081

http://bugs.mysql.com/bug.php?id=31188

http://bugs.mysql.com/bug.php?id=35819

http://bugs.mysql.com/bug.php?id=16247

http://www.mysqlperformanceblog.com/2008/04/04/multi-column-in-clause-unexpected-mysql-issue/

http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html#function_in

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics