sql优化-in数据量太多导致索引不生效
使用in导致索引不生效的常见解决方案
·
场景为:
table_a 是一个超过250万行的表
CREATE TABLE `table_a` (
`id` varchar(32) NOT NULL COMMENT 'id',
`user_id` int NOT NULL DEFAULT '0' COMMENT '用户id',
`status` tinyint NOT NULL DEFAULT '0',
...
...
`create_time` '创建时间',
`update_time` '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_user_id_status` (`user_id`,`status`) USING BTREE,
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='';
问题:
- 1,2,3只表示数量 真实数据非有序或连续
select * from table_a where user_id in(1,2,3, ... ,700) and status in(1,2);
查询需要大几十秒
问题分析:
使用explain 解析sql查询计划,发现mysql优化器未选择索引,idx_user_id_status索引失效,原因是条件user_id in的数据量大于700个,全表扫描导致查询时间长。
解决方案:
1.数据拆分
将in查询的数据拆分,将700条分为7条查询sql 每条只in100以内。
优点:避开优化器该机制,好理解
缺点:实现复杂,需要额外写代码组装sql。
2.使用虚拟表
将700个userId放入虚拟表中 然后使用连表查询,这样也会走索引查询时间为毫秒级。
create table tmp_user_id(user_id) as select * from (1,2,3,...700) ;
select * from table_a t1, tmp_user_id t2 where t1.user_id = t2.user_id and status in(1,2);
优点:原理简单,不需要额外写代码
缺点:sql相对复杂,需要建立虚拟表,及销毁该虚拟表。
3.强制索引(推荐)
使用强制索引 ,查询中增加关键字**FORCE INDEX (idx_user_id_status)**指定mysql的优化选择器强制使用该索引,使用索引后查询时间为毫秒级
select * from table_a FORCE INDEX (idx_user_id_status) where user_id in(1,2,3,...700) and status in(1,2);
优点:实现简单
缺点:强制该查询指定了索引,只能用于特定的某个方法
4.优化mysql配置
优先选择多索引而不是单索引
更多推荐


所有评论(0)