MySQL 中 where id in (1,2,3,4,...) 的效率问题讨论

MySQL

ACMAIN_CHM ACMAIN_CHM 06-26 16:36
等级 T12 84次回复

[求证&散分]MySQL 中 where id in (1,2,3,4,...) 的效率问题讨论

庆祝本月大版得分过万,兼把在这段论坛中经常被问到的一个问题拿出来大家讨论一下。

命题假设:

测试表如下

create table t_06 (
id int not null primary key,
c1 varchar(30),
i2 int
) engine = myisam; 

delimiter //

CREATE PROCEDURE prepareData_t_06 ()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i < 500000 DO
insert into t_06 values (i,concat('AA',i),i);
SET i = i + 1;
END WHILE;
END;
//

delimiter ;

CALL prepareData_t_06();

select count(*) from t_06;
show index from t_06;
show table status like 't_06';




现在如果由程序在数组中提供 100 个 ID 如下
38068,238833,308799,274344,299910,309823,337486,290812,56393,64413,492511,260426,58626,450987,499220,187731,365665,212799,227788,255724,384636,465766,417310,313148,483987,328761,402876,237274,249183,174185,28187,189155,259940,67800,60065,340172,311667,354861,182,305523,115981,365082,213915,47894,131301,198754,358852,112496,404423,486725,233123,322936,325337,125932,299260,128791,295663,469897,120580,347766,34859,364204,37597,268974,351155,256955,214013,309192,412394,216800,30315,411242,16678,233247,359013,401666,30792,452394,408649,14159,5519,91705,227648,120966,319599,351170,68129,368701,233566,144256,156172,41972,499687,390955,6549,298079,498230,196397,239493,242037

如何实现查询效率比较高,请给出你的意思,测试方案和对比结果者加分。

select * from t_06 where id in (38068,238833,308799,274344,299910,309823,337486,290812,56393,64413,492511,260426,58626,450987,499220,187731,365665,212799,227788,255724,384636,465766,417310,313148,483987,328761,402876,237274,249183,174185,28187,189155,259940,67800,60065,340172,311667,354861,182,305523,115981,365082,213915,47894,131301,198754,358852,112496,404423,486725,233123,322936,325337,125932,299260,128791,295663,469897,120580,347766,34859,364204,37597,268974,351155,256955,214013,309192,412394,216800,30315,411242,16678,233247,359013,401666,30792,452394,408649,14159,5519,91705,227648,120966,319599,351170,68129,368701,233566,144256,156172,41972,499687,390955,6549,298079,498230,196397,239493,242037);
 
wangxuantest wangxuantest 06-26 16:43
等级 T12 1楼

支持楼主  呵呵  有才人啊

liangCK liangCK 06-26 16:55
等级 T12 2楼

先接个分..再看.

apple_8180 apple_8180 06-26 16:56
等级 T12 3楼

将100已知ID写入一个临时表,然后用联结试试

Conry Conry 06-26 16:56
等级 T12 4楼

 

引用 2 楼 liangCK 的回复:
先接个分..再看.

up
netxuning netxuning 06-26 16:59
等级 T12 5楼

支持

liangCK liangCK 06-26 16:59
等级 T12 6楼

我认为分两步.
先将提供的ID转成行集.
ID
-----
38068
238833
308799
..

然后与表做JOIN操作.

apple_8180 apple_8180 06-26 17:05
等级 T12 7楼

 

引用 6 楼 liangCK 的回复:
我认为分两步. 
先将提供的ID转成行集. 
ID 
----- 
38068 
238833 
308799 
.. 

然后与表做JOIN操作.


我3楼就是这个意思。

实际还要对比 Join 和 In 在本例中那个效率高
WWWWA WWWWA 06-26 17:11
等级 T12 8楼

1、
直接用IN

select * from  t_06 a inner join lsbtest b on a.id=b.id1;



2、用LSBTEST

DROP TABLE IF EXISTS `lsbtest`;
CREATE TABLE `lsbtest` (
  `id1` bigint(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `lsbtest` */

LOCK TABLES `lsbtest` WRITE;

insert  into `lsbtest`(`id1`) values (1),(2),(38068),(238833),(308799),(274344),(299910),(309823),(337486),(290812),(56393),(64413),(492511),(260426),(58626),(450987),(499220),(187731),(365665),(212799),(227788),(255724),(384636),(465766),(417310),(313148),(483987),(328761),(402876),(237274),(249183),(174185),(28187),(189155),(259940),(67800),(60065),(340172),(311667),(354861),(182),(305523),(115981),(365082),(213915),(47894),(131301),(198754),(358852),(112496),(404423),(486725),(233123),(322936),(325337),(125932),(299260),(128791),(295663),(469897),(120580),(347766),(34859),(364204),(37597),(268974),(351155),(256955),(214013),(309192),(412394),(216800),(30315),(411242),(16678),(233247),(359013),(401666),(30792),(452394),(408649),(14159),(5519),(91705),(227648),(120966),(319599),(351170),(68129),(368701),(233566),(144256),(156172),(41972),(499687),(390955),(6549),(298079),(498230),(196397),(239493),(242037);

UNLOCK TABLES;

select * from  t_06 a inner join lsbtest b on a.id=b.id1;



WWWWA WWWWA 06-26 17:21
等级 T12 9楼

1、
select * from t_06 where id in (38068,238833,308799,274344,299910,309823,337486,290812,56393,64413,492511,260426,58626,450987,499220,187731,365665,212799,227788,255724,384636,465766,417310,313148,483987,328761,402876,237274,249183,174185,28187,189155,259940,67800,60065,340172,311667,354861,182,305523,115981,365082,213915,47894,131301,198754,358852,112496,404423,486725,233123,322936,325337,125932,299260,128791,295663,469897,120580,347766,34859,364204,37597,268974,351155,256955,214013,309192,412394,216800,30315,411242,16678,233247,359013,401666,30792,452394,408649,14159,5519,91705,227648,120966,319599,351170,68129,368701,233566,144256,156172,41972,499687,390955,6549,298079,498230,196397,239493,242037);


(100 row(s) returned)
Execution Time : 00:00:00:000
Transfer Time  : 00:00:00:000
Total Time     : 00:00:00:000


2、
select * from  t_06 a inner join lsbtest b on a.id=b.id1;
lsbtest:没有索引

(102 row(s) returned)
Execution Time : 00:00:00:000
Transfer Time  : 00:00:00:000
Total Time     : 00:00:00:000


如果直接运行1、2则两者在速度上基本相近

但2如果加上建表、插入数据,则
DROP TABLE IF EXISTS `lsbtest`; 
CREATE TABLE `lsbtest` ( 
  `id1` bigint(10) DEFAULT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

/*Data for the table `lsbtest` */ 

insert  into `lsbtest`(`id1`) values (1),(2),(38068),(238833),(308799),(274344),(299910),(309823),(337486),(290812),(56393),(64413),(492511),(260426),(58626),(450987),(499220),(187731),(365665),(212799),(227788),(255724),(384636),(465766),(417310),(313148),(483987),(328761),(402876),(237274),(249183),(174185),(28187),(189155),(259940),(67800),(60065),(340172),(311667),(354861),(182),(305523),(115981),(365082),(213915),(47894),(131301),(198754),(358852),(112496),(404423),(486725),(233123),(322936),(325337),(125932),(299260),(128791),(295663),(469897),(120580),(347766),(34859),(364204),(37597),(268974),(351155),(256955),(214013),(309192),(412394),(216800),(30315),(411242),(16678),(233247),(359013),(401666),(30792),(452394),(408649),(14159),(5519),(91705),(227648),(120966),(319599),(351170),(68129),(368701),(233566),(144256),(156172),(41972),(499687),(390955),(6549),(298079),(498230),(196397),(239493),(242037); 



select * from  t_06 a inner join lsbtest b on a.id=b.id1;

Total Time     : 00:00:01:094
Total Time     : 00:00:00:250
Total Time     : 00:00:00:015

大约1.359秒

lastyang lastyang 06-26 18:10
等级 T12 10楼

帮顶

nettman nettman 06-26 18:10
等级 T12 11楼

友情UP!

LongYongkai LongYongkai 06-26 21:28
等级 T12 12楼

UP

kaifaye
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值