Ker*_*mit 9 sql-server sql-server-2008-r2
我创建了一个接受开始和结束日期的函数,结束日期是可选的。然后我CASE
在过滤器中写了一个,如果没有通过结束日期,则使用开始日期。
CASE WHEN @dateEnd IS NULL
THEN @dateStart
ELSE @dateEnd
END
Run Code Online (Sandbox Code Playgroud)
当我为最近一个月的数据调用函数时:
SELECT * FROM theFunction ('2013-06-01', NULL)
Run Code Online (Sandbox Code Playgroud)
...查询挂起。如果我指定结束日期:
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
Run Code Online (Sandbox Code Playgroud)
... 结果正常返回。我从函数中取出代码并在查询窗口中正常运行。我也不能复制小提琴的问题。像这样的查询:
SELECT * FROM theFunction ('2013-04-01', '2013-06-01')
Run Code Online (Sandbox Code Playgroud)
...也工作正常。
查询(下面)中是否有任何内容可能导致函数NULL
在结束日期传递时挂起?
您的初始查询的一部分如下。
FROM [dbo].[calendar] a
LEFT JOIN [dbo].[colleagueList] b
ON b.[Date] = a.d
WHERE DAY(a.[d]) = 1
AND a.[d] BETWEEN @dateStart AND COALESCE(@dateEnd,@dateStart)
Run Code Online (Sandbox Code Playgroud)
计划的那部分如下所示
您修改后的查询 BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
具有相同的连接
不同之处似乎是ISNULL
进一步简化,因此您可以获得更准确的基数统计信息进入下一个连接。这是一个内联表值函数,您使用文字值调用它,因此它可以执行类似的操作。
a.[d] BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
a.[d] BETWEEN '2013-06-01' AND ISNULL(NULL,'2013-06-01')
a.[d] BETWEEN '2013-06-01' AND '2013-06-01'
a.[d] = '2013-06-01'
Run Code Online (Sandbox Code Playgroud)
由于有一个 equi join 谓词b.[Date] = a.d
,计划也显示了一个相等谓词b.[Date] = '2013-06-01'
。因此,28,393
行的基数估计可能非常准确。
对于CASE
/COALESCE
版本 when@dateStart
和@dateEnd
is 相同的值,那么它会将 OK 简化为相同的相等表达式并给出相同的计划,但是 when@dateStart = '2013-06-01'
和@dateEnd IS NULL
it only as far as
a.[d]>='2013-06-01' AND a.[Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END
Run Code Online (Sandbox Code Playgroud)
它也适用于 的隐含谓词ColleagueList
。这次估计的行数是79.8
行。
下一个加入是
LEFT JOIN colleagueTime
ON colleagueTime.TC_DATE = colleagueList.Date
AND colleagueTime.ASSOC_ID = CAST(colleagueList.ID AS VARCHAR(10))
Run Code Online (Sandbox Code Playgroud)
colleagueTime
是一个3,249,590
行表,它(再次)显然是一个没有有用索引的堆。
这种估计差异会影响所使用的连接选择。该ISNULL
计划选择只扫描表一次的散列连接。该COALESCE
计划选择了一个嵌套循环连接,并估计它仍然只需要扫描一次表并能够假脱机结果并重放它 78 次。即它估计相关参数不会改变。
由于嵌套循环计划在两小时后仍在进行,因此单次扫描的假设colleagueTime
似乎非常不准确。
至于为什么两个连接之间的估计行数如此之低,我不确定无法看到表上的统计信息。在我的测试中,我设法使估计的行数倾斜的唯一方法是添加NULL
行负载(这减少了估计的行数,即使返回的实际行数保持不变)。
COALESCE
我的测试数据计划中的估计行数为
number of rows matching >= condition * 30% * (proportion of rows in the table not null)
Run Code Online (Sandbox Code Playgroud)
或者在 SQL 中
SELECT 1E0 * COUNT([Date]) / COUNT(*) * ( COUNT(CASE
WHEN [Date] >= '2013-06-01' THEN 1
END) * 0.30 )
FROM [dbo].[colleagueList]
Run Code Online (Sandbox Code Playgroud)
但这与您对该列没有NULL
值的评论不符。
归档时间: |
|
查看次数: |
1175 次 |
最近记录: |