Любые идеи о том, как улучшить производительность этого запроса?Медленный запрос TSQL
[ftsIndex] PK is sID, wordPos.
И есть индекс для wordID, sID, wordPos.
Все они инт.
В конце используйте отдельный.
У большинства sID всего несколько матчей.
Некоторые sID могут иметь более 10 000 совпадений и убивать запрос.
Имейте запрос, где первые 27 749 строк возвращаются через 11 секунд.
Никакой сингл sID не имеет более 500 матчей.
Сумма индивидуальных матчей: 65,615.
Только 27 750-й ряд занимает более 2 минут и имеет 15 000 матчей.
Не удивительно, поскольку соединение в конце находится на [sID].
Поскольку в конце концов использовать отчетливый есть путь к нему, чтобы посмотреть на первый утвердительный
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
также поддерживают запросы, как «шустрая» 10 слов «лиса» или «койот», так соединяется с псевдонимами не хороший путь.
Это занимает 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 документов, имеющих более 7000 матчей.
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
@djangojazz Эта вставка занимает всего 5 секунд.Если я добавлю сортировку, записи будут вставлены в порядке PK, а все равно 5 секунд. – Paparazzi
Нам понадобятся определения таблицы/ключа/индекса и план запроса (фактический). Кроме того, есть ли какие-либо основания для этого дизайна/подхода, а не только для полнотекстового поиска SQL Server? – RBarryYoung