2010-06-19 68 views
2

,如果你願意,你可以閱讀的背景故事,改變了我的非聚集索引的聚集索引的事情後,開始運行速度快了很多。初始查詢計劃需要2-3秒的問題仍然存在。但是,保留計劃查詢提示相對有所改進。查詢計劃緩存和性能

背景故事

我在那裏我存儲的東西我想在一個簡單的搜索實現查找(雖然沒有什麼簡單的有關搜索)的倒排索引。

當我進入這樣的「馬局」查詢它將創建這個SQL

SELECT EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p0 
INTERSECT 
SELECT EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p1 
[email protected] String --'ma%' 
[email protected] String --'br%' 

對於每一個檢索詞,還有另一種INTERSECTSELECT

而且在大多數情況下這工作得非常好。我已正確編制Term列索引,並檢查潛在瓶頸的執行計劃。如預期的那樣,索引包含大約150,000行並且搜索瞬間發生。

什麼有點刺激但是,是通常有一定級別的第一查詢需要很多時間來執行。我敢打賭,這是因爲查詢優化器正在重新評估執行計劃。但我應該如何處理這個問題?我對服務器運行的查詢越多,拖延的次數就越少,但每隔一個查詢需要花費大約2-3秒的時間。這不是什麼大不了的事,但有時會長很多,我只是看不清這是從哪裏來的,或者如何處理它。它應該是閃電般的。

編輯

模式是這樣的:

CREATE TABLE InvertedIndex (
    Term varchar(255) NOT NULL, 
    Ordinal tinyint NOT NULL, 
    EntityType tinyint NOT NULL, 
    EntityID int NOT NULL 
) 

這兩個指標分別是:

CREATE NONCLUSTERED INDEX IX_InvertedIndex ON InvertedIndex (Term) 
INCLUDE (Ordinal, EntityType, EntityID) 

CREATE NONCLUSTERED INDEX IX_InvertedIndex_Reverse ON InvertedIndex (EntityType, EntityID) 

這東西留下,會發生什麼是插入和刪除操作時指數(倒排索引)需求要更新並徹底重建,這是否會影響QUERY PLAN的使用?

這裏是一個完整的查詢的例子,它真的很慢atm,3-5秒,我不知道爲什麼... ORDER BY子句是爲了給與匹配某個位置的單詞更高的排序順序(先發生在結果集中),但是對於每個搜索詞來說,這已經成倍地變慢了。

WITH Search AS (
    SELECT EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p0 
    INTERSECT 
    SELECT EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p1 
    INTERSECT 
    SELECT EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p2 
) 
SELECT p.PersonID 
, p.FullName 
, p.Email 
, p.MobilePhone 
, p.HomeAddress 
, p.HomeCity 
FROM Search AS s 
INNER JOIN Person AS p ON p.PersonID = s.EntityID AND s.EntityType = @pPersonEntityType 
ORDER BY (CASE WHEN @p3 IN (SELECT Ordinal FROM InvertedIndex WHERE Term LIKE @p0 AND EntityID = s.EntityID AND EntityType = s.EntityType) THEN 0 ELSE 1 END) + (CASE WHEN @p4 IN (SELECT Ordinal FROM InvertedIndex WHERE Term LIKE @p1 AND EntityID = s.EntityID AND EntityType = s.EntityType) THEN 0 ELSE 1 END) + (CASE WHEN @p5 IN (SELECT Ordinal FROM InvertedIndex WHERE Term LIKE @p2 AND EntityID = s.EntityID AND EntityType = s.EntityType) THEN 0 ELSE 1 END) 
@p0 String --'ma%' 
@p1 String --'br%' 
@p2 String --'mi%' 
@p3 Int32 --1 
@p4 Int32 --2 
@p5 Int32 --3 

上述查詢的重點是查找所有條款在InvertedIndex,那麼,對於每一個檢索詞有一個交點,這是邏輯一起選擇,我想用它來限制搜索。序數表示該詞在索引時的原始位置。 InvertedIndex中的每個條目代表一個元組,並且如果搜索條件與該N元組的某個項目匹配,則認爲它是更好的匹配。這就是爲什麼我需要通過子查詢來做到這一點。但它真的很慢。

ANSWER

如果我改變IX_InvertedIndex一個聚集索引它由一個數量級的提高了查詢的速度(我不知道爲什麼雖然):

CREATE CLUSTERED INDEX IX_InvertedIndex ON InvertedIndex (Term) 
+0

這取決於...什麼是表確定指標和世界衛生大會t索引是否定義? – 2010-06-19 12:14:17

+0

你有一個主鍵和唯一的聚集索引? – gbn 2010-06-21 10:33:43

+0

不,我不需要它。至少,我在假設沒有理由在這裏添加這個操作。我是我錯了? – 2010-06-21 11:44:26

回答

2

如果要附加條款INTERSECT那麼每個查詢將會與不同。我懷疑(根據你所說的)最終你有一個緩存的計劃,每個INTERSECT子句的數量。一旦你有緩存的計劃,它運行OK。

您可以嘗試plan guides,每個INTERSECT子句的數量一個。

否則,您總是可以有一個選擇和假脫機結果臨時表和自加入。不知道它會如何運行,或者它是不錯的主意。

你的指數也應該在期限與INCLUDEEntityType, EntityID被覆蓋過

編輯,註釋之後。

考慮到相對簡單,您可以嘗試KEEP PLANplan forcing too以避免聽起來像重新編譯。

如果它是SQL Server 2008中,我建議OPTIMISE FOR UNKNOWN

最後,另一個念頭:做全線的數據類型是否匹配?

編輯:您應該改變指數(Term, EntityType, Ordinal, EntityID)沒有包含您正在使用所有列連接或過濾器

您還需要一個主鍵(期限序)應具有唯一性和集羣?太,.中有沒有從性能差和零散的數據

,並更改查詢到這有一個分開沒有任何優勢!

WITH Search AS 
(
    SELECT Ordinal, EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p0 AND EntityType = @pPersonEntityType 
    INTERSECT 
    SELECT Ordinal, EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p1 AND EntityType = @pPersonEntityType 
    INTERSECT 
    SELECT Ordinal, EntityType, EntityID FROM InvertedIndex WHERE Term LIKE @p2 AND EntityType = @pPersonEntityType 
) 
SELECT 
    p.PersonID, p.FullName, p.Email, p.MobilePhone, p.HomeAddress, p.HomeCity 
FROM 
    Search AS s 
    INNER JOIN 
    Person AS p ON p.PersonID = s.EntityID 
    LEFT JOIN 
    (SELECT 0 AS Ranking, @p3 AS RankOrdinal) O3 
    LEFT JOIN 
    (SELECT 0 AS Ranking, @p4 AS RankOrdinal) O4 
    LEFT JOIN 
    (SELECT 0 AS Ranking, @p5 AS RankOrdinal) O5 
ORDER BY --although, I can't see why you are doing + 
    ISNULL(O3.Ranking, 1) + 
    ISNULL(O4.Ranking, 1) + 
    ISNULL(O5.Ranking, 1) 
+0

索引包括EntityType,EntityID。但謝謝你指出。上個月我不知道。我要去調查計劃指南。儘管我想補充說執行計劃似乎比這更頻繁地改變。只是改變搜索值,仍然是相同的數字,但不同的值,可能會導致這種突然停頓。 – 2010-06-19 12:58:50

+0

@John Leidegren:我的意思是強迫計劃而不是計劃指南,對不起。計劃指南適用於無法更改SQL的情況。強制是增加查詢提示的東西。 – gbn 2010-06-19 13:13:46

+0

我確實嘗試了UNTINZE FOR UNKNOWN,但當它是SQL 2008功能時遇到了牆壁。我會嘗試下一步保持計劃。那麼我應該避免計劃指導?還沒有嘗試過...... – 2010-06-21 10:08:52