2013-06-05 70 views
0

問題查詢使用多個相交。TSQL優化多個相交

使用count()= 6將它更改爲in('alpha','beta','gamma','delta','epsilon','phi')組不是一個選項,因爲應用程序支持像通配符(如alpha%)。但count()= 6查詢在少於1秒內運行。

使用通配符可以使用多個連接,這就是它的結構。在4或更少的情況下,相交表現比多重聯結更好,但不幸的是沒有測試5或更多。

查詢對任何4個術語表現都很好 - 少於1秒。
字面上任何4 - 前4,後4或中4 4.
5或更多,然後它死了 - 我在2分鐘殺死查詢。
在6個術語讓它運行 - 5分鐘返回795行。

最多4個術語查詢計劃將循環與合併連接進行混合。
在5個或更多的術語中,查詢計劃都是循環連接。
是否有將查詢提示應用於相交的語法?

嘗試了兩套使用()()但沒有更改查詢計劃的3套。

(-- start term 
     select [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     where [ftsIndexWordOnce].[wordID] in ( 
      select [id] from [FTSwordDef] with (nolock) 
            where [word] like 'alpha') 
) -- end term 
INTERSECT 
    (-- start term 
     select [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     where [ftsIndexWordOnce].[wordID] in ( 
      select [id] from [FTSwordDef] with (nolock) 
            where [word] like 'beta') 
) -- end term 
INTERSECT 
    (-- start term 
     select [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     where [ftsIndexWordOnce].[wordID] in ( 
      select [id] from [FTSwordDef] with (nolock) 
            where [word] like 'gamma') 
) -- end term 
INTERSECT 
    (-- start term 
     select [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     where [ftsIndexWordOnce].[wordID] in ( 
      select [id] from [FTSwordDef] with (nolock) 
            where [word] like 'delta') 
) -- end term 
INTERSECT 
    (-- start term 
     select [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     where [ftsIndexWordOnce].[wordID] in ( 
      select [id] from [FTSwordDef] with (nolock) 
            where [word] like 'epsilon') 
) -- end term 
INTERSECT 
    (-- start term 
     select [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     where [ftsIndexWordOnce].[wordID] in ( 
      select [id] from [FTSwordDef] with (nolock) 
            where [word] like 'phi') 
) -- end term 

認爲我有一個修復

 select distinct [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     Inner Merge Join [FTSwordDef] with (nolock) 
     On [FTSwordDef].[ID] = [ftsIndexWordOnce].[wordID] 
     And [FTSwordDef].[word] like 'alpha' 
    INTERSECT 
    select distinct [ftsIndexWordOnce].[sID] 
     from [ftsIndexWordOnce] with (nolock) 
     Inner Merge Join [FTSwordDef] with (nolock) 
     On [FTSwordDef].[ID] = [ftsIndexWordOnce].[wordID] 
     And [FTSwordDef].[word] like 'beta' 

查詢優化器還是那張愚蠢的在5個以上,但是這會強制先加入是合併,並將其保存。

回答

1

可能想嘗試「存在」。 「IN」可能會變得昂貴,特別是對於大型列表。 「EXISTS」只是尋找第一場比賽,而「IN」則試圖找到他們。如果sID在ftsIndexWordOnce中是唯一的,則下面的代碼應該可以工作。如果沒有,你可以添加不同的或組。

編輯:第一個腳本有邏輯錯誤。看評論。

SELECT 
    [ftsIndexWordOnce].[sID] 
FROM 
    [ftsIndexWordOnce] WITH (NOLOCK) 
WHERE 
    EXISTS 
    (
     SELECT 
      NULL 
     FROM 
      [FTSwordDef] WITH (NOLOCK) 
     WHERE 
      [FTSwordDef].[word] LIKE 'alpha' 
      AND 
      [FTSwordDef].id = [ftsIndexWordOnce].wordid 
    ) 
INTERSECT 
SELECT 
    [ftsIndexWordOnce].[sID] 
FROM 
    [ftsIndexWordOnce] WITH (NOLOCK) 
WHERE 
    EXISTS 
    (
     SELECT 
      NULL 
     FROM 
      [FTSwordDef] WITH (NOLOCK) 
     WHERE 
      [FTSwordDef].[word] LIKE 'beta' 
      AND 
      [FTSwordDef].id = [ftsIndexWordOnce].wordid 
    ) 
INTERSECT 
SELECT 
    [ftsIndexWordOnce].[sID] 
FROM 
    [ftsIndexWordOnce] WITH (NOLOCK) 
WHERE 
    EXISTS 
    (
     SELECT 
      NULL 
     FROM 
      [FTSwordDef] WITH (NOLOCK) 
     WHERE 
      [FTSwordDef].[word] LIKE 'gamma' 
      AND 
      [FTSwordDef].id = [ftsIndexWordOnce].wordid 
    ) 
INTERSECT 
SELECT 
    [ftsIndexWordOnce].[sID] 
FROM 
    [ftsIndexWordOnce] WITH (NOLOCK) 
WHERE 
    EXISTS 
    (
     SELECT 
      NULL 
     FROM 
      [FTSwordDef] WITH (NOLOCK) 
     WHERE 
      [FTSwordDef].[word] LIKE 'delta' 
      AND 
      [FTSwordDef].id = [ftsIndexWordOnce].wordid 
    ) 
INTERSECT 
SELECT 
    [ftsIndexWordOnce].[sID] 
FROM 
    [ftsIndexWordOnce] WITH (NOLOCK) 
WHERE 
    EXISTS 
    (
     SELECT 
      NULL 
     FROM 
      [FTSwordDef] WITH (NOLOCK) 
     WHERE 
      [FTSwordDef].[word] LIKE 'epsilon' 
      AND 
      [FTSwordDef].id = [ftsIndexWordOnce].wordid 
    ) 
INTERSECT 
SELECT 
    [ftsIndexWordOnce].[sID] 
FROM 
    [ftsIndexWordOnce] WITH (NOLOCK) 
WHERE 
    EXISTS 
    (
     SELECT 
      NULL 
     FROM 
      [FTSwordDef] WITH (NOLOCK) 
     WHERE 
      [FTSwordDef].[word] LIKE 'phi' 
      AND 
      [FTSwordDef].id = [ftsIndexWordOnce].wordid 
    ) 
+0

不錯的想法,但AND返回0.很確定它一次只評估一個wordID,單個wordID不能像'alpha'和'beta'一樣。你怎麼看? – Paparazzi

+0

D'oh,對吧。所以回到交叉點,但用EXISTS而不是IN。以交叉位作爲子查詢的連接也可以工作。 – JAQFrost

+0

嘗試用INTERSECT存在,但仍然沒有解決它。在5或更多時,它會全部循環連接並死亡。但是,內部合併連接可能會訣竅。 – Paparazzi