6人参与 • 2026-08-03 • MsSqlserver
最近对一个存储过程进行优化,这里记录一下in在sqlserver中的一些优化和情况。

所以 union all其实是效率最好的,也就是 =any()
select * from tablea where name in ('a','b','c');
select * from tablea where name='a' or name='b' or name='c';
select *
from tablea a
where exists (
select 1
from ( values ('a'),('b'),('c')) as tmp(name)
-- sql server/postgresql/mysql 8.0+ 语法
select tablea.*
from tablea
join ( values ('a'),('b'),('c')) as tmp(name)
on tablea.name = tmp.name
select * from tablea where name='a' union all
select * from tablea where name='b' union all
select * from tablea where name='c '
或
select * from tablea where name = any('a','b','c');
实现
select * from tablea where
a.name in ('a','b','c')
and a.types in ('1','3','7','8')
and a.age in ('33','35','39')
存储过程
declare
@name varchar(100)='a,b,c',
@type varchar(100)='1,3,7,8',
@age varchar(100)='33,35,39'
--列转行
if object_id('tempdb..#mytemp') is not null
begin
drop table #mytemp
end
select * into #mytemptable1 from
(
select b.id,b.typeid
from (
select [value] = convert(xml, '<v>' + replace(@name,',', '</v><v>') + '</v>')
) a
outer apply(
select id = n.v.value('.', 'nvarchar(100)'),typeid=1
from a.[value].nodes('/v') n(v)
) b
union
select d.id,d.typeid
from (
select [value] = convert(xml, '<v>' + replace(@type,',', '</v><v>') + '</v>')
) c
outer apply(
select id = n.v.value('.', 'nvarchar(100)'),typeid=2
from c.[value].nodes('/v') n(v)
) d
union
select d.id,d.typeid
from (
select [value] = convert(xml, '<v>' + replace(@age,',', '</v><v>') + '</v>')
) e
outer apply(
select id = n.v.value('.', 'nvarchar(100)'),typeid=3
from c.[value].nodes('/v') n(v)
)f
) as t
--exists 子查询
select * from tablea a where
a.name in (select id from #mytemp where typeid=1)
and a.types in (select id from #mytemp where typeid=2)
and a.age in (select id from #mytemp where typeid=3)
有一个很奇怪的情况,当@name='a’时,存储过程中
select * from tablea a where a.name in (select id from #mytemp where typeid=1) and a.types in (select id from #mytemp where typeid=2) and a.age in (select id from #mytemp where typeid=3)
a.name... 比 a.name='a' 或 a.name in ('a') 查询时间多了一倍。 types、age 确没影响
改成join后,得到解决:
select * from tablea a join #mytemptable1 b on b.id = a.dataareaid and b.typeid=1 where a.types in (select id from #mytemp where typeid=2) and a.age in (select id from #mytemp where typeid=3)
在in 不走索引的情况下,union all 效率最高
再改进:
select * from tablea a join #mytemptable1 b on b.id = a.dataareaid and b.typeid=1 where a.types = any(select id from #mytemp where typeid=2) and a.age = any(select id from #mytemp where typeid=3)
如果有索引, 几种方式效率差不多。没有索引都避免不了全表查询。
in 列表包含大量值(如上千个)时,或者优化器以为in会包含大量值,
可能生成低效的执行计划。
改成join 效果可能有质的飞跃。
如: a.name in (select id from #mytemp where typeid=1)
计划会以为 in 里的值会很多,给出很糟糕的执行计划。
效率无绝对,由「数据量、索引、执行计划」决定,常规业务场景下的高效层级为:union all ≈ join(等值连接) > exists > in > or
但考虑到 union all 不去重的特性, join+临时表的用法应该是最值得推荐的。
到此这篇关于sql中优化in的几种方法的文章就介绍到这了,更多相关sql 优化in内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论