Как добавить больше запросов ИЛИ с помощью CONTAINS. Приводит запрос к сканированию?
У меня есть простой запрос, который основывается на двух полнотекстовых индексированных таблицах, но он выполняется очень медленно, когда у меня есть СОДЕРЖАНИЕ, объединенное с любым дополнительным поиском ИЛИ. Как видно из плана выполнения, два полнотекстовых поиска снижают производительность. Если я запрашиваю только 1 из КОНТЕЙНОВ или ни того, ни другого, запрос будет менее секунды, но в тот момент, когда вы добавляете ИЛИ в микс, запрос становится неудачным.
Эти две таблицы не являются чем-то особенным, они не слишком широкие (42 столбца в одной, 21 столбец в другой; возможно, 10 столбцов являются индексированными FT в каждой) или даже содержат очень много записей (36 тысяч записей в самой большой из двух).
Я был в состоянии решить производительность путем разделения два СОДЕРЖИТ поиск в свои собственные запросы SELECT, а затем UNION три вместе. Является ли это решение от UNION моей единственной надеждой?
SELECT a.CollectionID
FROM collections a
INNER JOIN determinations b ON a.CollectionID = b.CollectionID
WHERE a.CollrTeam_Text LIKE '%fa%'
OR CONTAINS(a.*, '"*fa*"')
OR CONTAINS(b.*, '"*fa*"')
План выполнения:
![execution plan]()
Ответы
Ответ 1
Мне было бы интересно узнать, будет ли LEFT JOIN эквивалентным CONTAINSTABLE работать лучше. Что-то вроде:
SELECT a.CollectionID
FROM collections a
INNER JOIN determinations b ON a.CollectionID = b.CollectionID
LEFT JOIN CONTAINSTABLE(a, *, '"*fa*"') ct1 on a.CollectionID = ct1.[Key]
LEFT JOIN CONTAINSTABLE(b, *, '"*fa*"') ct2 on b.CollectionID = ct2.[Key]
WHERE a.CollrTeam_Text LIKE '%fa%'
OR ct1.[Key] IS NOT NULL
OR ct2.[Key] IS NOT NULL
Ответ 2
Я собирался предложить UNION
каждому в качестве своего собственного запроса, но когда я прочитал ваш вопрос, я увидел, что вы это нашли. Я не могу придумать лучшего способа, поэтому, если он поможет ему. Метод UNION
- это общий подход к плохо выполняющемуся запросу, который имеет несколько условий ИЛИ, каждый из которых хорошо работает сам по себе.
Ответ 3
Я бы, вероятно, использовал UNION. Если вы действительно против, вы можете попробовать что-то вроде:
SELECT a.CollectionID
FROM collections a
LEFT OUTER JOIN (SELECT CollectionID FROM collections WHERE CONTAINS(*, '"*fa*"')) c
ON c.CollectionID = a.CollectionID
LEFT OUTER JOIN (SELECT CollectionID FROM determinations WHERE CONTAINS(*, '"*fa*"')) d
ON d.CollectionID = a.CollectionID
WHERE a.CollrTeam_Text LIKE '%fa%'
OR c.CollectionID IS NOT NULL
OR d.CollectionID IS NOT NULL
Ответ 4
У нас есть одна и та же проблема, и в то же время мы поставили ее на плохо сформированный запрос - что SQL 2005 позволил нам уйти от него, но 2008 год не будет.
В итоге мы разделили запрос на 2 SELECT, которые вызывались с использованием IF. Рад, что у кого-то была такая же проблема и что это известная проблема. Мы видели запросы на столе с ~ 150 000 строк + полный текст, идущий от < 1 секунда (2005) до 30+ секунд (2008).