У меня есть простой запрос, который полагается на две полнотекстовых индексированных таблицы, но он работает чрезвычайно медленный, когда мне объединили СОДЕРЖАНИЕ с любым дополнительным ИЛИ поисковым. Как замечено в плане выполнения, эти два полнотекстовых поиска сокрушают производительность. Если я запрашиваю со всего 1 из СОДЕРЖАНИЯ, или ни один, запрос является подвторым, но момент, который Вы добавляете ИЛИ в соединение, запрос становится злополучным.
Эти две таблицы являются ничем специальным, они не чрезмерно широки (42 седла в один, 21 в другом; возможно, 10 седлами является FT, индексированный в каждом), или даже содержите очень много записей (36k, обращает внимание в самом большом из двух).
Я смог решить производительность путем разделения этих двух, СОДЕРЖИТ поиски в их собственные Запросы Select и затем ОБЪЕДИНЕНИЕ три вместе. Является это обходное решение ОБЪЕДИНЕНИЯ моей единственной надеждой?
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*"')
План выполнения:
Мне было бы любопытно посмотреть, будет ли 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
Я собирался предложить UNION
каждый в качестве отдельного запроса, но когда я прочитал ваш вопрос, я увидел, что вы это нашли. Я не могу придумать лучшего способа, так что если это поможет, используйте его. Метод UNION
- это распространенный подход к неэффективному запросу, который имеет несколько условий OR, каждое из которых хорошо работает само по себе.
Мы столкнулись с точно такой же проблемой и в то время объяснили это тем, что наш запрос был плохо сформирован - мол, SQL 2005 позволил нам избежать этого, а 2008 - нет.
В итоге мы разделили запрос на 2 SELECT, которые вызывались с помощью IF. Рад, что кто-то еще столкнулся с такой же проблемой и что это известная проблема. Мы наблюдали, как запросы к таблице с ~150 000 строк + полный текст выполнялись от < 1 секунды (2005) до 30+ секунд (2008).
Я бы, наверное, использовал 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