簡體   English   中英

SQL Server 2008 R2:調優查詢

[英]SQL Server 2008 R2: Tuning query

我有下表有10億條記錄。

create table PfTest
(
    cola int,
    colb int,
    colc date,
    cold varchar(10),
    ID int
);

現在我想顯示特定日期而不是特定日期的記錄。

我正在使用以下兩種類型的查詢:

查詢1:

select DISTINCT cola, colb, colc, cold, ID
from PfTest
WHERE colc In ('2014-01-01') 
  AND cold NOT IN (SELECT cold 
                   FROM PfTest 
                   WHERE ID = 1 
                     AND colc IN ('2014-01-02', '2014-01-03', 
                                  '2014-01-04', '2014-01-05', '2014-01-06'));

查詢2:

WITH cte AS
(
    SELECT DISTINCT cola, colb, colc, cold, ID
    FROM PfTest
    WHERE cold NOT IN (SELECT cold FROM PfTest 
                       WHERE ID = 1 
                         AND colc IN('2014-01-02', '2014-01-03',
                                     '2014-01-04', '2014-01-05', '2014-01-06'))
) 
SELECT cola, colb, colc, cold, ID
FROM cte 
WHERE colc IN ('2014-01-01');   

以上兩個查詢計划都是相同的執行。 兩者都需要花費大量時間來執行。 我可以為這種情況寫一些更好的查詢嗎?

這是您的查詢,沒有DISTINCT (這似乎是不必要的):

select cola, colb, colc, cold, ID
from PfTest
WHERE colc In ('2014-01-01') AND 
      cold NOT IN (SELECT cold
                   from PfTest
                   WHERE ID = 1 AND
                         colc IN ('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06')
                  );

我會從索引開始。 PFTest(colc, cold)PFTest(id, colc, cold)

如果子查詢返回大量數據 - 比如數百萬行 - 那么這可能是您最好使用臨時表的情況。 我會先嘗試索引。 如果這不起作用,那么帶有cold索引的臨時表可能會起作用。 此外,雖然它對性能影響不大,但我會使用NOT EXISTS而不是NOT IN來表達查詢:

select cola, colb, colc, cold, ID
from PfTest t
WHERE colc In ('2014-01-01') AND 
      NOT EXISTS (SELECT 1
                  from PfTest t2
                  WHERE t2.cold = t1.cold AND t2.ID = 1 AND
                        t2.colc IN ('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06')
                 );

對於此版本,最佳索引是PfTest(cold, id, colc)

當匹配列具有NULL值時, NOT EXISTS具有更直觀的行為。

首先

 
 
 
 
  
  
  select DISTINCT cola, colb, colc, cold, ID from PfTest WHERE colc In ('2014-01-01') AND cold NOT IN (SELECT cold FROM PfTest WHERE ID = 1 AND colc IN ('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06'));
 
 
  

和...一樣

 
 
 
 
  
  
  select DISTINCT cola, colb, colc, cold, ID from PfTest WHERE colc In ('2014-01-01') AND colc NOT IN ('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06')
 
 
  

AND NOT(ID = 1);

因為內表和外表是相同的。

由於您不想一次又一次地重復使用表(因為它占用了十億行),因此將數據提取到臨時表是一種更好的做法。 然后在其上創建合適的索引。

 select cola, colb, colc, cold, ID INTO #PfTest FROM PfTest CREATE NONCLUSTERED INDEX IX_PFTEST1 ON #PfTest(id) INCLUDE (cola, colb, colc, cold) CREATE NONCLUSTERED INDEX IX_PFTEST2 ON #PfTest(colc) INCLUDE (cola, colb, id, cold) CREATE NONCLUSTERED INDEX IX_PFTEST3 ON #PfTest(cold) INCLUDE (cola, colb, id, colc) select cola, colb, colc, cold, ID from #PfTest WHERE colc In ('2014-01-01') INTERSECT select cola, colb, colc, cold, id from (select cola, colb, colc, cold, ID from #PfTest EXCEPT SELECT cola, colb, colc, cold, 1 id FROM #PfTest where colc IN('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06'))A 

使用EXCEPT代替NOT IN來改善性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM