Генерация плана SQL-запроса занимает 5 минут, сам запрос выполняется за миллисекунды. Что происходит? - PullRequest
10 голосов
/ 11 апреля 2010

У меня есть довольно сложная (или уродливая, в зависимости от того, как вы на это смотрите) хранимая процедура, работающая на SQL Server 2008. Она основывает большую логику на представлении, которое имеет таблицу pk и таблицу fk. Таблица fk оставляется присоединенной к таблице pk чуть более 30 раз (таблица fk имеет плохой дизайн - она ​​использует пары «имя-значение», которые мне нужно выровнять. К сожалению, это сторонняя организация, и я не могу ее изменить).

В любом случае, он работал нормально в течение нескольких недель, пока я периодически не замечал пробежку, которая занимала бы 3-5 минут. Оказывается, это время, которое требуется для генерации плана запроса. Как только план запроса существует и кэшируется, сама хранимая процедура выполняется очень эффективно. Все идет гладко, пока нет причин для повторного создания и кэширования плана запросов.

Кто-нибудь видел это? Почему создание плана занимает так много времени? Есть ли способы, чтобы заставить его придумать план быстрее?

Ответы [ 3 ]

4 голосов
/ 11 апреля 2010

Вы можете попробовать использовать Plan Guide .Генерация плана еще продлится некоторое время, но должна быть значительно короче.

3 голосов
/ 11 апреля 2010

Что-то привело к тому, что план потребовал перекомпиляции, например, обновление статистики или изменение DDL. Список здесь: Кэширование и повторное использование плана выполнения

Запрос в его текущей форме всегда будет занимать 3-5 минут для перекомпиляции: этого нельзя избежать.

Если вы не можете изменить его (PIVOT, используйте триггер для поддержания "правильной" таблицы и т. Д.), Тогда вы можете контролировать только, когда происходит перекомпиляция.

Ответ гида по плану Ремуса - один из способов. Я также посмотрел бы на свою статистическую поддержку и удостоверился, что это сделано за одну ночь, так что это происходит только один раз в начале дня

2 голосов
/ 11 апреля 2010

Рассматривали ли вы переписать свой SELECT с 30-ю присоединениями к чему-то подобному?

SELECT [key], NULL AS [a], NULL AS [b]
  INTO #temp
  FROM [pk-table]

UPDATE t SET t.[a] = fk.[a], t.[b] = fk.[b]
  FROM #temp t
  INNER JOIN (
    SELECT f.[key],
      MAX(CASE WHEN f.[name] = 'a' THEN f.[value] ELSE NULL END) AS [a],
      MAX(CASE WHEN f.[name] = 'b' THEN f.[value] ELSE NULL END) AS [b]
    FROM [fk-table] f
    GROUP BY f.[key]
    ) fk ON (fk.[key] = t.[key]

Хотя, возможно, это не ответ на ваш первоначальный вопрос:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...