表達對列
首先,不管你用什麼樣的功能,把它在WHERE子句中或JOIN條件中對錶中的一列是次優的。做一個常數的數學和比較。您的WHERE子句中應該是這樣的:
ff.startDate < DateAdd(day, 1, @curdate) -- if @curdate has time portion removed
ff.startDate < DateAdd(day, 1, dbo.fn_GetDateOnly(@curdate)) -- if @curdate has time
對於在給定日期一般尋找項目,使用這個模式:
WHERE
DateCol >= '20120901'
AND DateCol < '20120902'
把任何功能上等號的另一側列,這應該是孤獨的。它可以幫助你查找如何使一個表達式SARGABLE。如果列必須位於兩側,則將所有表達式放在執行計劃中「左」輸入的一側(其數據先到達,LOOP JOIN的外循環或一個LOOP JOIN的「表」一側哈希連接)。例如,如果你想做到這一點:
WHERE dbo.fn_getDateOnly(A.DateCol) = dbo.fn_getDateOnly(B.DateCol)
然後假設A.DateCol至上在執行計劃中,切換到:
WHERE
B.DateCol >= DateAdd(day, DateDiff(day, 0, A.DateCol), 0)
AND B.DateCol < DateAdd(day, DateDiff(day, 0, A.DateCol), 0)
(或使用內嵌版本函數如下,但我覺得它是尷尬的,所以沒有額外的價值是間接的)。
如果這種查詢將在所涉及的表上頻繁進行,那麼可能需要重新設計一些重新設計,或者添加一個刪除了時間部分(可能被索引)的持久計算列,以便將日期時間轉換爲單獨的日期和時間字段,或將其存儲爲開頭的日期(如果您確實不需要日期時間)。
注意:當然,對dbo.fn_getDateOnly的引用可以簡單地替換爲DateAdd(day, DateDiff(day, 0, DateCol), 0)
。此外,如果值爲datetime
數據類型,則只需執行DateCol + 1
而不是使用DateAdd
(不過要小心,因爲這對於SQL 2008和更高版本中的date
數據類型不起作用)。
的UDF
的直列能力對於SELECT子句中的函數的性能,SQL Server只內聯「內聯函數」,而不是標量函數。改變你的函數返回一個單行記錄CREATE FUNCTION ... RETURNS TABLE AS RETURN (SELECT ...)
,並使用它,像這樣:
SELECT
(SELECT DateValue FROM dbo.fn_GetDateOnly(Col)),
...
這真的是不超過一個參數化的視圖不同。
在WHERE子句中使用這個內聯版本會變得笨拙。做DateDiff幾乎更好。在SQL 2008中,當然只是使用Convert(date, DateCol)
,但仍然遵循關於在哪裏放置計算表達式(與列中等號相反的一側)的規則。
一定要投票inline scalar UDFs on Microsoft Connect!你遠離唯一一個認爲這個功能非常缺乏的人。
如果可能的話,您應該儘量避免圍繞列進行任何類型的函數調用。 'WHERE ff.startDate
2012-07-23 15:45:07