2014-11-06 127 views
0

我有一個SQL查詢需要幾個小時才能運行。基本上,我期待在我們的「頁面」表格中找到具有特殊字符的文檔(PDF)。我在PDFFile表中找到這些PDF。執行第一個AND子句將在16秒內返回。添加第二個子句使SQL花費3小時。試圖找出我做錯了什麼。任何幫助是極大的讚賞。SQL命令運行緩慢。需要幫助識別緩慢

查詢:

select b.bookletname, b.trackingID, b.[version], s.name 
from page p 
inner join section s on s.id = p.sectionid 
inner join booklet b on b.id = s.bookletid 
INNER JOIN [user] u ON b.CreatedBy = u.id 
INNER JOIN client c ON c.id = u.clientID 
WHERE u.clientID = 2 
AND p.[filename] IN (
    SELECT DISTINCT pdf.[FileName] 
    FROM PDFFile pdf 
    WHERE pdf.fileName LIKE '%\<%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\>%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\"%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\%%' ESCAPE '\' 
    OR pdf.fileName LIKE '%''%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\*%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\+%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\\%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\/%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\:%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\?%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\[%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\]%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\|%' ESCAPE '\' 
) 
OR p.[PDF_File_Name] IN (
    SELECT DISTINCT pdf.[FileName] 
    FROM PDFFile pdf 
    WHERE pdf.fileName LIKE '%\<%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\>%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\"%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\%%' ESCAPE '\' 
    OR pdf.fileName LIKE '%''%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\*%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\+%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\\%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\/%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\:%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\?%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\[%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\]%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\|%' ESCAPE '\' 
) 
OR p.[PDFName] IN (
    SELECT DISTINCT pdf.[FileName] 
    FROM PDFFile pdf 
    WHERE pdf.fileName LIKE '%\<%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\>%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\"%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\%%' ESCAPE '\' 
    OR pdf.fileName LIKE '%''%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\*%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\+%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\\%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\/%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\:%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\?%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\[%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\]%' ESCAPE '\' 
    OR pdf.fileName LIKE '%\|%' ESCAPE '\' 
) 
+1

有那麼多'LIKE',這怎麼可能不慢呢? – Lamak 2014-11-06 16:49:43

+0

爲什麼您的PDF表格有兩個單獨的文件列?如果其中一個是空的,你可以使用'COALESCE()'嗎? – Kevin 2014-11-06 16:56:11

+0

@Lamak:特別是用'LIKE'和一個前導'%' - >確保**沒有索引**可以使用! – 2014-11-06 17:03:48

回答

2

exists重寫這個,並簡化like s。 SQL Server允許你在模式中有字符列表,並且你所擁有的大部分字符都不需要轉義(我希望我的結果模式完全正確)。

我會建議:

select b.bookletname, b.trackingID, b.[version], s.name 
from page p inner join 
    section s 
    on s.id = p.sectionid inner join 
    booklet b 
    on b.id = s.bookletid inner join 
    [user] u 
    on b.CreatedBy = u.id inner join 
    client c 
    on c.id = u.clientID 
where u.clientID = 2 and 
     (exists (select 1 
       from PDFFile pdf 
       where pdf.fileName LIKE '%[<>"''*+\\/:?\[\]|]%' ESCAPE '\' and 
        pdf.fileName = p.filename 
      ) or 
     exists (select 1 
       from PDFFile pdf 
       where pdf.fileName LIKE '%[<>"''*+\\/:?\[\]|]%' ESCAPE '\' and 
        pdf.fileName = p.PDF_File_Name 
      ) or 
     exists (select 1 
       from PDFFile pdf 
       where pdf.fileName LIKE '%[<>"''*+\\/:?\[\]|]%' ESCAPE '\' and 
        pdf.fileName = p.PDFName 
      ) 
    ); 

你要確保你的PDFFile(fileName)性能有一個索引。

我也改變了邏輯。您的原始邏輯像where A and B or C or D這被解析爲where (A and B) or C or C。我將其更改爲where A and (B or C or D)。這也可能是導致性能瓶頸的原因。

+0

嘿@Gordon Linoff。絕對對你的答案感興趣,但它有語法錯誤... Msg 102,Level 15,State 1,Line 14 '\'附近的語法不正確。 消息105,級別15,狀態1,行24 字符串'和 pdf.fileName = p之後未封閉的引號。 PDF名稱 ) ) '。 – 2014-11-07 01:22:16

+0

不知道如何解決,或者我會。 – 2014-11-07 01:23:49

+0

修正了它。這真太了不起了。謝謝! – 2014-11-07 19:56:54

2

嘗試取出三次表命中,並將該選擇到臨時表,因爲你使用的是相同的選擇要檢查三列。所以你可以在任何情況下使用臨時表。

SELECT DISTINCT pdf.[FileName] 
INTO #temp 
FROM PDFFile pdf 
WHERE pdf.fileName LIKE '%\<%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\>%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\"%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\%%' ESCAPE '\' 
     OR pdf.fileName LIKE '%''%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\*%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\+%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\\%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\/%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\:%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\?%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\[%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\]%' ESCAPE '\' 
     OR pdf.fileName LIKE '%\|%' ESCAPE '\' 

SELECT b.bookletname, 
     b.trackingID, 
     b.[version], 
     s.NAME 
FROM page p 
     INNER JOIN section s 
       ON s.id = p.sectionid 
     INNER JOIN booklet b 
       ON b.id = s.bookletid 
     INNER JOIN [user] u 
       ON b.CreatedBy = u.id 
     INNER JOIN client c 
       ON c.id = u.clientID 
WHERE u.clientID = 2 
     AND p.[filename] IN (SELECT * 
          FROM #temp) 
     OR p.[PDF_File_Name] IN (SELECT * 
           FROM #temp) 
     OR p.[PDFName] IN (SELECT * 
          FROM #temp) 
+0

這工作。明確的性能提升。從3小時到10分鐘。試着用+1來嘗試其他解決方案,看看他的解決方案是否表現更好。謝謝你的答案d(-_-)b – 2014-11-07 01:20:19