表:Table
id:自动编号
ST:数字
表的记录大概有100万条左右
现在需要的是:
Select id From [Table] Where [id] in(1,2,3,4,5,................................) and [ST] = 0
但由于in()里面的数据太大,有上千条,导致出现以下错误问题:
查询处理器用尽了内部资源,无法生成查询计划。这种情况很少出现,只有在查询极其复杂或引用了大量表或分区时才会出现。
求解决思路?
------解决方案--------------------
动态拼接成 id=1 or id=2…………
------解决方案--------------------
几千个就直接生成一张表吧。 放到表里面 跟当前表 inner join 一下。
------解决方案--------------------
我试过上千个id之后是会出现这种情况,并且联机丛书上对in的解释中也有这样的说法,改成left join之类的才行
------解决方案--------------------
建议改为区间来查
Select id From [Table] Where [ST] = 0 and ([id]>=1 and id <=5 or id>=100 and id<=10000)
------解决方案--------------------
把数据存储在临时表然后用JOIN的办法,这么多IN会导致执行计划无法生成的。
------解决方案--------------------
Select id From [Table] Wherecharindex(id,'1,2,3……‘)>0 and [ST] = 0
这样呢?
------解决方案--------------------
因为in本质就是or,优化器对每个or都要做分析,过多的or会导致优化器无法分析,最后报错
------解决方案--------------------
我觉得不用那么麻烦把。
讨论下,这个可用?
Select id From [Table] Where charindex(id,'1,2,3……‘)>0 and [ST] = 0
------解决方案--------------------
这个要看数据量了,当年遇到这个类似情况的时候还不会用charindex,所以没测过是否不抱错。不过这个函数基本上就是表扫描或索引扫描,所以可能性能没那么好。如果换成集合,加上索引,可能能用得上
------解决方案--------------------
他要in那么多的数据,怎么着效率也上不了去。至少实现起来简单,但是效率还得实测。
------解决方案--------------------
他要in那么多的数据,怎么着效率也上不了去。至少实现起来简单,但是效率还得实测。
------解决方案--------------------
你用局部临时表就可以避免并发问题,tempdb开大一点,放到IO快的盘上,问题不大。另外一个字段进行处理,就要看看如何整合进去。
------解决方案--------------------
用join你是觉得麻烦还是慢?
------解决方案--------------------
假设你已经有了这个ID的集合,假设为#t,那么你现在需要怎么对另外一个字段进行判断?
------解决方案--------------------
在你这个例子中,In始终是个性能杀手
------解决方案--------------------
Select id From [Table] Where [id] in(select id from 表) and [ST] = 0
如果这些ID是程序中华拼接的 就没好办法了
------解决方案--------------------
楼主还是试试看能不能用left join吧 估计其他的方法都不太好用
------解决方案--------------------
4、用DBA_Huangzj 提供的方法,只能取1600多条记录,耗时1秒左右,
将@s varchar(8000)修改为@s nvarchar(max),与方法3同样的ID集,耗时超过5分钟后未完成,手动取消执行。
------解决方案--------------------
另外你每次都要对百万级的数据进行操作?
------解决方案--------------------
改了一下,你试试,几万个不应该还要2分钟的
if exists(select * from sys.objects where name = 'f_splitSTR' and type = 'tf')
drop function dbo.f_splitSTR
go
create function dbo.f_splitSTR
(
@s varchar(max), --要分拆的字符串
@split varchar(10) --分隔字符
)
returns @re table( --要返回的临时表
col varchar(max) --临时表中的列
)
as
begin
declare @len int
set @len = LEN(@split) --分隔符不一定就是一个字符,可能是2个字符
while CHARINDEX(@split,@s) >0
begin
insert into @re
values(left(@s,charindex(@split,@s) - 1))
set @s = STUFF(@s,1,charindex(@split,@s) - 1 + @len ,'') --覆盖:字符串以及分隔符
end
insert into @re values(@s)
return --返回临时表
end
go
declare @res varchar(100)