2015-07-28 46 views
0

我有一個包含這麼多SET語句的存儲過程。這需要很長的時間來執行。我能做些什麼來提高表現。我在這裏列出了一個聲明。SQL性能與不同和計數

SET @VisitedOutlets=(select count (distinct CustomerId) from dbo.VisitDetail 
         where RouteId = @intRouteID 
         and CONVERT(VARCHAR(10),VisitDate,111) between CONVERT(VARCHAR(10),@FromDate,111) 
         and CONVERT(VARCHAR(10),@ToDate,111)); 
+0

什麼是VisitDate,@ FromDate,@ ToDate的數據類型 –

+0

所有3列數據類型都是DATETIME – Tom

+0

您在VisitDetail表中有多少條記錄? –

回答

0

我認爲你的問題來自你在查詢中使用變量的事實。通常,優化器將...優化(!)給定(硬編碼)值的查詢(比如id = 123),而不能優化,因爲它是一個變量。

讓我們從here一個很好的例子:

OK,

  1. 你是優化和查詢計劃是車輛。

  2. 我會給你一個查詢,你必須選擇車輛。

  3. 所有在圖書館的圖書上的序列號

我的查詢是去圖書館,讓我所有的書3和5

之間你會選擇一個合適的自行車,快速,便宜,高效,足以讓 帶回3本書。

新查詢。

轉到圖書館,獲取@x和@y之間的所有書籍。

挑車。

繼續。

這就是發生了什麼事。如果我要求書籍 介於1和Maxvalue之間,你會選擇自卸車嗎?如果x = 3和y = 5,那就太過分了。 SQL必須 在看到數字之前選擇該計劃。

所以你的問題是優化器不能正確地完成它的工作。爲了讓他完成他的工作,你可以讓他重新編譯或更新統計數據。參見here,herehere

所以我的2個解決方案,您的問題將是:

  1. RecompileOPTION(RECOMPILE)

  2. Update statisticsEXEC sp_updatestats

0

您的查詢基本上是:

select @VisitedOutlets= count(distinct CustomerId) 
from dbo.VisitDetail 
where RouteId = @intRouteID and 
     CONVERT(VARCHAR(10), VisitDate, 111) between 
      CONVERT(VARCHAR(10), @FromDate, 111) and CONVERT(VARCHAR(10), @ToDate, 111); 

我認爲這個查詢可以優化來利用索引。一個主要問題是日期比較。您不應該在VisitDate上進行任何轉換。所以,我就重寫查詢爲:

select @VisitedOutlets= count(distinct CustomerId) 
from dbo.VisitDetail vd 
where vd.RouteId = @intRouteID and 
     vd.VisitDate >= cast(@FromDate as date) and 
     vd.VisitDate < dateadd(day, 1, cast(@ToDate as date)) 

對於此查詢,您想對​​的索引。我也會以適當的格式存儲常量,因此查詢本身不需要轉換。

between使用日期是危險的。 Here是Aaron Bertrand關於這個話題的有趣討論。