Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 TOP from Full Text Search  [new]
igor2222
Member

Откуда: Харків
Сообщений: 1233
Подскажите пожалуйста,
есть табличка на 3 млн строк с PK.
Нужно получить TOP50 последних значений (по дате) при существующем FullText индексе.
Т.е. нужно:
select top 50 *
FROM Content.Table1
where (CONTAINS (Title, 'Main'))
ORDER BY StartDate DESC
Такой запрос работает больше минуты (ФТС находит 450 тыс. строк, потом мапит на PK, потом сортирует и потом возвращает первые 50). Индекс по дате есть, но он не используется (судя по плану).
При этом вот такой запрос:
select top 50 *
FROM Content.Table1
where (CONTAINS (Title, 'Main'))
работает 1 секунду.
Как правильно скрестить слона с носорогом?
WITH (INDEX (IX_StartDate))
делает только хуже.
Заполнять темповую таблицу с 450 тыс строк- больше 40 секунд...
Использовать like - больше 13 секунд...
А надо 3-4 сек, не больше...
Можно ли как-то ФТС индекс завязать с датой и отсортировать? Понимаю, что бред, но всё же...
select @@VERSION 
Microsoft SQL Server 2012 (SP4) (KB4018073) - 11.0.7001.0 (X64)   Aug 15 2017 10:23:29   Copyright (c) Microsoft Corporation  Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor) 

Хелп! :)
9 апр 19, 11:35    [21856894]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 6532
igor2222,

не уверен, но попробуйте построить кластерный индекс по StartDate. Некластерный не сможет повлиять на порядок просмотра записей таблицы.
9 апр 19, 11:59    [21856932]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
invm
Member

Откуда: Москва
Сообщений: 8661
Если PK кластерный, попробуйте так
select
 d.*
from
 (
  select top (50)
   a.PK
  from
   Content.Table1 a inner loop join 
   containstable(Content.Table1, Title, 'Main') b on b.[KEY] = a.PK
  order by
   a.StartDate desc
 ) c join
 Content.Table1 d on d.PK = c.PK
9 апр 19, 12:26    [21856977]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
igor2222
Member

Откуда: Харків
Сообщений: 1233
Владислав Колосов
igor2222,

не уверен, но попробуйте построить кластерный индекс по StartDate. Некластерный не сможет повлиять на порядок просмотра записей таблицы.

К сожалению, не вариант. PK кластерный. На него завязаны форейны. Я положу остальной перфоманс...
9 апр 19, 12:53    [21857008]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
igor2222
Member

Откуда: Харків
Сообщений: 1233
invm
Если PK кластерный, попробуйте так...

Спасибо, но пока не получилось :(
Весь селект остановил после 4х минут...
Внутренний с сортировкой остановил после 4х минут...
Внутренний без сортировки тоже не дождался...
А вот
select * from containstable
выбрал 659 тыс за 5 сек...
Как бы умудриться его сортирнуть на лету?
9 апр 19, 13:00    [21857017]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
invm
Member

Откуда: Москва
Сообщений: 8661
igor2222
Весь селект остановил после 4х минут...
Внутренний с сортировкой остановил после 4х минут...
Внутренний без сортировки тоже не дождался...
Лучше планы показывать, хотя бы оценочные. И не картинкой, а в формате sqlplan

igor2222
Как бы умудриться его сортирнуть на лету?
Никак.
9 апр 19, 13:26    [21857066]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
invm
Member

Откуда: Москва
Сообщений: 8661
igor2222,

Можете попробовать вот такой изврат:
1. Добавить в таблицу вычисляемый столбец
alter table add TitleWithRecordAge as Title + ' RecordAge:' + cast(datediff(day, getdate(), '99991231') as varchar(10))
и добавить его в FTI.
Также выключить стоп-лист.

2. Написать функцию:
create function dbo.fnGetMatchedByDate
(
 @SearchString varchar(100),
 @Date date
)
returns @result table (PK int primary key)
as
begin
 select @SearchString = @SearchString + ' and ' + cast(datediff(day, @Date, '99991231') as varchar(10));

 insert inot @result
  (PK)
  select [KEY] from containstable(Content.Table1, TitleWithRecordAge, @SearchString);

 return;
end;


3. Обеспечить в БД заполненую таблицу натуральных чисел, начиная с нуля.

4. Переписать запрос так:
select
 d.*
from
 (
  select top (50)
   b.PK
  from
   [Таблица чисел] a cross apply 
   dbo.fnGetMatchedByDate('Main', dateadd(day, a.Число, getdate()) b
 ) c join
 Content.Table1 d on d.PK = c.PK
9 апр 19, 14:00    [21857139]     Ответить | Цитировать Сообщить модератору
 Re: TOP from Full Text Search  [new]
igor2222
Member

Откуда: Харків
Сообщений: 1233
invm
igor2222,
Можете попробовать вот такой изврат:


Спасибо! В прямом виде не получилось, но мысль поймал и результат есть! :)
15 апр 19, 17:12    [21862836]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить