【问题标题】:Sql IN clause slows down performanceSql IN 子句会降低性能
【发布时间】:2014-01-12 22:26:01
【问题描述】:

我需要关于 sql 查询性能的帮助...

我有一个视图,当我运行视图时

select * 
from udv_salesAnalyze 
where _month=12 and _year=2012 

我在 2 秒内得到结果

但是当我添加另一个过滤器时

select * from udv_salesAnalyze 
where _month=12 and _year=2012 
and userRef in (1,2,5,6,9,11,12,13,14
,19,22,25,26,27,31,34,35,37,38,39,41,47,48,49,53,54,57,59,61,62
,65,66,67,68,69,70,74,77,78,79,80,83,86,87,88,90,91,92,94)  

我在 1 分 38 秒内得到结果..

我将查询修改为

select * from udv_salesAnalyze 
where _month=12 and _year=2012 
and userRef in (select * from udf_dependedUsers(2)) 

(这里 udf_dependedUsers 是表返回函数)我在 38 秒内得到结果

我加入了 table retuned 函数来查看,但我又在 38-40 秒内得到了结果...

有没有其他方法可以更快地得到结果...

非常感谢您能给我一个解决方案...

非常感谢...

这里是 udf_dependedUsers 的代码:

ALTER FUNCTION [dbo].[udfn_dependedUsers] (@userId int)
RETURNS @dependedUsers table (userRef int)
AS
BEGIN
DECLARE @ID INT
SET @ID = @userId
;WITH ret AS(SELECT userId FROM users
             WHERE  userId = @ID
             UNION ALL
             SELECT t.userId
             FROM   users t INNER JOIN ret r ON t.Manager = r.userId
             ) 
insert into @dependedUsers (userRef)
select * from ret
order by userId
RETURN 
END

【问题讨论】:

  • 确保userRef 参与了适当的索引。
  • 是什么定义了你拥有的这个值列表?
  • 我有组织架构,当我使用该函数时,我得到了用户的依赖用户列表的结果集...例如 udf_dependedUsers(2) 给出了用户依赖于用户的结果集Id 2.. 该函数运行速度快...在 0 秒内返回结果
  • 你能把代码贴在 UDF 里吗?
  • 这令人困惑:您的 UDF 似乎与您的原始常量列表无关。更糟糕的是,它是一个递归 CTE,几乎是性能不佳的一个公式。请澄清你在这里真正想要做什么。此外,udv_salesAnalyze 对象显然不是一个简单的表选择,因此我们还需要查看它的定义。

标签: sql sql-server performance in-clause


【解决方案1】:

尝试使用左连接

select * from udv_salasAnalyze  MainTable
LEFT JOIN
(select * from udf_dependedUsers(2)) SelectiveInTable --Try direct query like that you wrote in user function
ON SelectiveInTable.userRef = MainTable.userRef
where _month=12 and _year=2012 
and SelectiveInTable.userRef != null

【讨论】:

  • @GökhanYılmaz 您是否尝试在 LEFT JOIN 而不是 UDF 中直接查询
【解决方案2】:

使用 JOIN 而不是 IN,如下所示:

select 
   data.* 
from udv_salesAnalyze data
join ( values
    (1), (2), (5), (6), (9),(11),(12),(13),(14),(19)
   ,(22),(25),(26),(27),(31),(34),(35),(37),(38),(39)
   ,(41),(47),(48),(49),(53),(54),(57),(59)
   ,(61),(62),(65),(66),(67),(68),(69),(70),(74),(77),(78),(79)
   ,(80),(83),(86),(87),(88),(90),(91),(92),(94)
) V(userRef) on V.userRef = data.userRef
where _month = 12
  and _year  = 2012 

【讨论】:

【解决方案3】:

问题是保存用户数据的表的索引

这里是解决方案;

1-将您的查询写入查询编辑器并单击“显示估计的执行计划”按钮..

2- SQL Server 为您提供有关“执行计划窗口”中应在表上创建的索引的提示和查询

3- 右键单击​​执行计划窗口并选择“缺少索引详细信息”

4- 在打开的查询页面中重命名索引名称([] 为您想要的其他名称)并运行查询

5- 并运行你自己的查询,正如我在问题中提到的那样很慢......在这些步骤之后,我的查询在 4 秒而不是 38 秒内运行

【讨论】:

  • 但是你说查询select * from udv_salesAnalyze where _month=12 and _year=2012跑了两个!尽管该索引可能很有用,但它并不是全部。当IN 存在时,可能不同的基数估计会影响计划选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 2012-07-02
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 2011-11-20
  • 2016-01-12
相关资源
最近更新 更多