问题查询使用多个Intersect。
通过使count()= 6将其更改为in('alpha','beta','gamma','delta','epsilon','phi')组不是一个选项,因为应用程序支持像通配符(例如alpha%)。但count()= 6查询运行时间不到1秒。
使用通配符可以使用多个连接,这就是它过去的结构。在4或更低时,Intersect的性能优于多个连接,但不幸的是,它不会在5或更高的情况下进行测试。
查询在任何4个术语中都表现出色 - 不到1秒。 字面意思是任何4 - 前4,后4或中4。 在5或更多然后它死了 - 我在2分钟杀死了查询。 在6个条款让它运行 - 5分钟返回795行。
查询计划最多4个术语将循环与合并连接混合在一起。 在5个或更多个术语中,查询计划是所有循环连接。 是否有将查询提示应用于Intersect的语法?
尝试了两组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或更多时愚蠢,但这会强制第一个连接成为合并并保存它。
可能想尝试“EXISTS”。 “IN”可能会变得昂贵,特别是对于大型列表。 “EXISTS”只是寻找第一场比赛,而“IN”则试图找到它们。如果sID在ftsIndexWordOnce中是唯一的,则下面的代码应该有效。如果没有,您可以在其上添加distinct或group。
编辑:第一个脚本有逻辑错误。看评论。
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
)
我和你的问题非常相似。
我想知道未定义的交叉数的常见值是什么。
由于性能损失,我无法使用动态SQL。
所以我提出了如下模式:
WITH CTE AS (
SELECT [FTSwordDef].[ID], -- Unique identifier of the referenced entity
[ftsIndexWordOnce].[sID] -- The field that should be common for the intersect
FROM [FTSwordDef]
INNER JOIN [ftsIndexWordOnce]
ON [FTSwordDef].[ID] = [ftsIndexWordOnce].[wordID]
-- All your intersects becomes a query that returns all the participants of interest
WHERE [FTSwordDef].[word] IN ('alpha','beta','gamma','delta','epsilon','phi')
-- Optional GROUP BY if you don't trust the integrity of
-- your data and fear duplicate data may be present
GROUP BY [FTSwordDef].[ID],[ftsIndexWordOnce].[sID]
)
SELECT [MAIN].[sID] -- The common value you wanted with the intersect
FROM CTE [MAIN]
-- We count the amount of participating entities (N Amount of intersect)
CROSS APPLY(
SELECT COUNT(DISTINCT [A].[ID]) C FROM CTE [A]
) [A]
-- We count the occurrences of the common value
CROSS APPLY(
SELECT COUNT([B].[sID]) C FROM CTE [B] WHERE [B].[sID] = [MAIN].[sID]
) [B]
-- If the value we want in common has equal occurrences as the amount of
-- participating referenced entities, we can say the value is common for all
WHERE [A].[C] = [B].[C]
GROUP BY [MAIN].[sID]