У меня довольно сложный запрос, который иногда очень медленно возвращает результаты. С самого начала было ясно, что виновником является часть предложения WHERE, связанная с полнотекстовым поиском. Поэтому я изолировал его и протестировал. В результате этого тестирования выяснилось, когда это произойдет, но я пока не понял, как это исправить. Вот в чем проблема:
Мне нужно отфильтровать один, два или три столбца с полнотекстовым индексом в зависимости от того, что хочет сделать пользователь. Поскольку кажется, что список столбцов в предикате CONTAINS не может быть представлен как переменная, следующее лучшее, что я мог придумать, - это использовать некоторую стандартную логическую логику, например:
(((@SearchInName = 0 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 0) OR @SearchExpression = '""')
OR (@SearchInName = 1 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 0 AND CONTAINS(ProductName, @SearchExpression))
OR (@SearchInName = 0 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 0 AND CONTAINS(ProductShortDescr, @SearchExpression))
OR (@SearchInName = 0 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 1 AND CONTAINS(ProductDescrHTML, @SearchExpression))
OR (@SearchInName = 1 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 0 AND CONTAINS((ProductName, ProductShortDescr), @SearchExpression))
OR (@SearchInName = 1 AND @SearchInShortDescr = 0 AND @SearchInHTMLDescr = 1 AND CONTAINS((ProductName, ProductDescrHTML), @SearchExpression))
OR (@SearchInName = 0 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 1 AND CONTAINS((ProductShortDescr, ProductDescrHTML), @SearchExpression))
OR (@SearchInName = 1 AND @SearchInShortDescr = 1 AND @SearchInHTMLDescr = 1 AND CONTAINS((ProductName, ProductShortDescr, ProductDescrHTML), @SearchExpression))
Это было бы хорошо и работало бы так, как ожидалось (быстро), пока фактическое допустимое условие совпадает с последним разделом ИЛИ. Таким образом, в приведенном выше примере это будет, когда @SearchInName = 1 И @SearchInShortDescr = 1 И @SearchInHTMLDescr = 1 (пользователь хочет искать во всех 3 столбцах). Другие условия ТАКЖЕ быстро возвращаются, если они помещаются последними в этом блоке кода. Однако, как только фактическое допустимое условие выше, чем последнее, кажется, что все последующие за ним операторы CONTAINS также запускаются (хотя и не обязательно включаются в результаты, что является правильным), что занимает время выполнения от менее 1 с до 6. секунд или более в зависимости от того, насколько высок допустимый оператор и, следовательно, сколько других предикатов CONTAINS следует за ним. Очевидный вывод из этого состоит в том, что по какой-то причине следующие логические операторы не могут выполнить короткое замыкание и запустить предикат CONTAINS, несмотря ни на что.
Я понимаю, что порядок выполнения не всегда определяется фактическим кодом и что после оптимизации SQL некоторые короткие замыкания могут работать не так, как задумано, благодаря ему, что, похоже, именно в этом случае. Обычно предлагается использовать оператор CASE для обеспечения порядка, но, к сожалению, оператор CONTAINS, похоже, вообще не подходит для оператора CASE.
Поэтому я думаю, что, вероятно, знаю, почему это происходит (оптимизация SQL), но не могу понять, как это исправить. Кто-нибудь может помочь?
CASE
(раньше я полагал, чтоCASE
можно использовать для наложения порядка, но оказалось, что это не так) - person Damien_The_Unbeliever   schedule 13.09.2012