У нас есть интересная проблема, на которую я надеялся, что кто-то может помочь пролить свет на это. На высоком уровне проблема как ниже:
Следующий запрос выполняется быстро (1 секунда):
SELECT SA.*
FROM cg.SEARCHSERVER_ACTYS AS SA
JOIN CONTAINSTABLE(CG.SEARCHSERVER_ACTYS, NOTE, 'reports') AS T1 ON T1.[Key]=SA.UNIQUE_ID
но если мы добавим фильтр к запросу, то возврат займет примерно 2 минуты:
SELECT SA.*
FROM cg.SEARCHSERVER_ACTYS AS SA
JOIN CONTAINSTABLE(CG.SEARCHSERVER_ACTYS, NOTE, 'reports') AS T1 ON T1.[Key]=SA.UNIQUE_ID
WHERE SA.CHG_DATE>'19 Feb 2010'
Глядя на план выполнения для двух запросов, я вижу, что во втором случае есть два места, где существуют огромные различия между фактическим и предполагаемым количеством строк, а именно:
1) Для табличной функции FulltextMatch, в которой оценка составляет приблизительно 22 000 строк, а фактическая - 29 миллионов строк (которые затем объединяются до 1670 строк перед объединением) и
2) Для поиска индекса по полнотекстовому индексу, где оценка составляет 1 строку, а фактическая - 13 000 строк
В результате оценок оптимизатор решил использовать объединение вложенных циклов (поскольку оно предполагает небольшое количество строк), следовательно, план неэффективен.
Мы можем обойти эту проблему, либо (а) параметризовав запрос и добавив в запрос OPTION (OPTIMIZE FOR UNKNOWN), либо (b) заставив использовать HASH JOIN. В обоих случаях запрос возвращается через 1 секунду, и оценки представляются разумными.
Мой вопрос действительно заключается в том, «почему оценки, используемые в случае с плохими показателями, настолько дико неточны, и что можно сделать, чтобы улучшить их»?
Статистика в актуальном состоянии по индексам в индексированном представлении, используемом здесь.
Любая помощь с благодарностью.