【发布时间】:2013-05-29 21:31:41
【问题描述】:
关于如何提高此查询性能的任何想法?
[ftsIndex]
PK 是 sID,wordPos。
并且在wordID、sID、wordPos上有一个索引。
他们都是int。
最后使用不同的。
大多数 sID 仅有几个匹配项。
某些 sID 可能有超过 10,000 个匹配项并终止查询。
有一个查询,前 27,749 行在 11 秒内返回。
没有一个 sID 有超过 500 个匹配项。
个人匹配的总和为 65,615。
仅第 27,750 行就耗时 2 分钟,有 15,000 场比赛。
这并不奇怪,因为最后的连接位于 [sID] 上。
既然最终使用 distinct 有没有办法找到第一个 肯定的
on [wXright].[sID] = [wXleft].[sID]
and [wXright].[wordPos] > [wXleft].[wordPos]
and [wXright].[wordPos] <= [wXleft].[wordPos] + 10
然后移动到下一个 sID?
我知道这对查询优化器提出了很多要求,但这真的很酷。
在现实生活中,问题文档是零件清单,供应商重复了很多次。
select distinct [wXleft].[sID]
FROM
( -- begin [wXleft]
( -- start term
select [ftsIndex].[sID], [ftsIndex].[wordPos]
from [ftsIndex] with (nolock)
where [ftsIndex].[wordID] in
(select [id] from [FTSwordDef] with (nolock)
where [word] like 'Brown')
) -- end term
) [wXleft]
join
( -- begin [wRight]
( -- start term
select [ftsIndex].[sID], [ftsIndex].[wordPos]
from [ftsIndex] with (nolock)
where [ftsIndex].[wordID] in
(select [id] from [FTSwordDef] with (nolock)
where [word] like 'Fox')
) -- end term
) [wXright]
on [wXright].[sID] = [wXleft].[sID]
and [wXright].[wordPos] > [wXleft].[wordPos]
and [wXright].[wordPos] <= [wXleft].[wordPos] + 10
这将它降低到 1:40
inner loop join
我这样做只是为了尝试,它完全改变了查询计划。
我不知道问题查询需要多长时间。我在 20:00 放弃了。
我什至不打算将此作为答案发布,因为我认为它对其他人没有价值。
希望有更好的答案。
如果我在接下来的两天内没有收到,我将删除该问题。
这并不能解决问题
select distinct [ft1].[sID]
from [ftsIndex] as [ft1] with (nolock)
join [ftsIndex] as [ft2] with (nolock)
on [ft2].[sID] = [ft1].[sID]
and [ft1].[wordID] in (select [id] from [FTSwordDef] with (nolock) where [word] like 'brown')
and [ft2].[wordID] in (select [id] from [FTSwordDef] with (nolock) where [word] like 'fox')
and [ft2].[wordPos] > [ft1].[wordPos]
and [ft2].[wordPos] <= [ft1].[wordPos] + 10
还支持诸如“quick brown”之类的带有 10 个单词的“fox”或“coyote”的查询,因此使用别名连接不是一个好路径。
这需要 14 分钟(但至少会运行)。
同样,这种格式不利于更高级的查询。
IF OBJECT_ID(N'tempdb..#tempMatch1', N'U') IS NOT NULL DROP TABLE #tempMatch1
CREATE TABLE #tempMatch1(
[sID] [int] NOT NULL,
[wordPos] [int] NOT NULL,
CONSTRAINT [PK1] PRIMARY KEY CLUSTERED
(
[sID] ASC,
[wordPos] ASC
))
IF OBJECT_ID(N'tempdb..#tempMatch2', N'U') IS NOT NULL DROP TABLE #tempMatch2
CREATE TABLE #tempMatch2(
[sID] [int] NOT NULL,
[wordPos] [int] NOT NULL,
CONSTRAINT [PK2] PRIMARY KEY CLUSTERED
(
[sID] ASC,
[wordPos] ASC
))
insert into #tempMatch1
select [ftsIndex].[sID], [ftsIndex].[wordPos]
from [ftsIndex] with (nolock)
where [ftsIndex].[wordID] in
(select [id] from [FTSwordDef] with (nolock)
where [word] like 'Brown')
--and [wordPos] < 100000;
order by [ftsIndex].[sID], [ftsIndex].[wordPos]
insert into #tempMatch2
select [ftsIndex].[sID], [ftsIndex].[wordPos]
from [ftsIndex] with (nolock)
where [ftsIndex].[wordID] in
(select [id] from [FTSwordDef] with (nolock)
where [word] like 'Fox')
--and [wordPos] < 100000;
order by [ftsIndex].[sID], [ftsIndex].[wordPos]
select count(distinct(#tempMatch1.[sID]))
from #tempMatch1
join #tempMatch2
on #tempMatch2.[sID] = #tempMatch1.[sID]
and #tempMatch2.[wordPos] > #tempMatch1.[wordPos]
and #tempMatch2.[wordPos] <= #tempMatch1.[wordPos] + 10
一个稍有不同的连接在 5 秒内运行(并且具有不同的查询计划)。
但是我无法通过提示来修复它,因为它会移动到一个连接的位置。
甚至 +1 也有超过 10 个文档,其中包含超过 7,000 个匹配项。
on [wXright].[sID] = [wXleft].[sID]
and [wXright].[wordPos] = [wXleft].[wordPos] + 1
全表定义
CREATE TABLE [dbo].[FTSindex](
[sID] [int] NOT NULL,
[wordPos] [int] NOT NULL,
[wordID] [int] NOT NULL,
[charPos] [int] NOT NULL,
CONSTRAINT [PK_FTSindex] PRIMARY KEY CLUSTERED
(
[sID] ASC,
[wordPos] ASC
)WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[FTSindex] WITH CHECK ADD CONSTRAINT [FK_FTSindex_FTSwordDef] FOREIGN KEY([wordID])
REFERENCES [dbo].[FTSwordDef] ([ID])
GO
ALTER TABLE [dbo].[FTSindex] CHECK CONSTRAINT [FK_FTSindex_FTSwordDef]
GO
【问题讨论】:
-
我不知道你的所有数据,但你有没有想过可能插入临时表,然后在它们上创建聚集索引?先插入,再创建索引。这通常比自己创建索引要快。这可能会对您有所帮助,但可能不会,所以我想将其添加为评论。
-
@djangojazz 插入只需要 5 秒。如果我添加一个排序,以便以 PK 顺序插入记录,它仍然是 5 秒。
-
我们将需要表/键/索引定义和查询计划(实际)。此外,这种设计/方法是否有任何理由,而不是仅使用 SQL Server 全文搜索?
-
SQL Server 全文搜索在 "fox 或 "coyote" 的 10 内不做 "quick brown"。将添加 table def。你如何发布查询计划?
-
您必须将它放到某个在线共享中并链接到它。 (我最不喜欢 StackOverflow 的东西)
标签: tsql join sql-server-2008-r2