2013-06-05 49 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