2012-12-03 19 views
1

這從以前的問題排序如下操作:非常慢使用SQL Server查詢功能

SQL Server Query time out depending on Where Clause

在其中查詢將運行得非常慢取決於where子句。我重寫了該查詢使用CTE,並很好地避免了這個問題,但從來沒有找到答案。

最近調整了另一個相似的查詢以添加另一個字段,突然它的性能下降了大約30秒,運行並返回10,000行,超過10個小時(並最終返回相同的結果集)。今天我開始排查這個問題,發現一些奇怪的東西。

我經常需要提取的日期只有部分從日期時間價值,所以我寫的邏輯成一個函數:

CREATE FUNCTION [dbo].[cDate] (@pInputDate DATETIME) 
RETURNS DATETIME 
BEGIN 
     RETURN CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME) 
END 
GO 

我在這個新的,效率低下的查詢發現,如果我取代了功能與在查詢中嵌入CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME),查詢執行速度從〜10小時下降到略低於2秒。我估計執行計劃沒有什麼區別。順便說一下,這不是添加的字段。我假設增加另一個領域以某種方式導致執行計劃改變並擴大了上述條件。

我的問題是,這是正常的嗎?如上所述,我利用重複流程的功能,因爲它們更容易維護,記住並更新,如果您找到更有效的方式做某事。我應該爲我的職能做些什麼來改善他們的表現嗎?

+4

是的,這是衆所周知的。搜索標量值函數。這是RBAR ... –

+0

SQL Server的**版**是你的嗎?也許'CAST(@pInputDate AS DATE)'會更有效率(這將工作於** 2008 **或更新版本)... –

+0

不幸的是,我現在被困在2005年,所以這不是一個選項。 – Molloch

回答

0

我會嘗試添加另一個變量來做聲明並返回。對此的思考過程可能是您的投射和轉換以改變您輸入的日期時間可能是瓶頸。這可能不是這種情況,但是如果你在範圍中設置了一個新變量,那麼經常進行調節並將其綁定到該變量並返回該變量,這可能有助於提高速度。如果可能,我傾向於遠離標量函數,但當您開始將它們用於較大的數據集時,它們會遇到很多性能問題。只是一個建議,可能或可能不會幫助,但它會隔離返回一個新的對象獨立輸入:

CREATE FUNCTION [dbo].[cDate] (@pInputDate DATETIME) 
RETURNS DATETIME 
BEGIN 
Declare @Output datetime = CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME) -- 2008 method and newer 

Declare @Output datetime; 

Select @Output = CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME) -- 2005 and prior method 


return @Output 
END 
GO 
5

如果你必須在一個函數封裝這一看Scalar functions, inlining, and performance: An entertaining title for a boring post

改寫如下

CREATE FUNCTION dbo.cDate_Inline 
(
    @pInputDate DATETIME 
) 
RETURNS TABLE 
AS 
    RETURN 
    (
     SELECT DATEADD(day, DATEDIFF(Day, 0, @pInputDate), 0) AS [Date] 
    ) 

然後,而不是

SELECT *, 
     [dbo].[cDate](modify_date) AS modified 
FROM sys.objects 

使用

SELECT *, 
     ca.Date AS modified 
FROM sys.objects 
     CROSS APPLY dbo.cDate_Inline(modify_date) ca 

這將由查詢優化程序內聯到計劃中。

+0

救命,THX!拯救了我噸的重構:) – xhafan