2013-03-15 2 views
1

У меня есть SQL запрос ищет что-то вроде этого:Одно условие замедляет SQL запрос резко

WITH RES_CTE AS 
    (SELECT 
    COLUMN1, 
    COLUMN2, 
    [MORE COLUMNS...] 
    ROW_NUMBER() OVER (ORDER BY R.RANKING DESC) AS RowNum 
    FROM TABLE1 As R, TABLE2 As A, TABLE3 As U, TABLE4 As S, TABLE5 As T 
    WHERE R.RID = A.LID 
    AND S.QRYID = R.QRYID 
    AND A.AID = U.AID 
    AND CONDITION1 = 'VALUE' 
    AND CONDITION2 = 'VALUE' 
    AND [MORE CONDITIONS...] 
), 
Results_Cnt AS 
    (SELECT COUNT(*) CNT FROM Results_CTE) 
SELECT * FROM Results_CTE, Results_Cnt WHERE RowNum >= 1 AND RowNum <= 25 

Теперь этот запрос, как правило, работает под 1 сек и возвращает 25 записей из 5000 на основе CONDITION1.

В последнее время я добавил новый столбец в TABLE1, а затем использовал его значения как CONDITION2 в запросе выше. Столбец заполняется в будущем, но все значения в прошлом: NULL.

Я прочитал что-то выше таблицы соединения, в которой есть NULL, являющийся причиной медленного выполнения. В таблице содержится около 1 300 000 записей. 90% из них - NULL в проблемной колонке. Но эта колонка не соединяется. (Тот, который является соединяемых на имеет INDEX)

Однако, я хотел бы попробовать, что в любом случае, создав новый столбец и просто скопировать данные следующим образом:

ALTER TABLE TABLE1 ADD COL_NEW 
UPDATE TABLE1 SET COL_NEW = COL_OLD 

Мой следующий шаг был чтобы заменить NULL на фактическое значение, но сначала, просто для ударов, я изменил запрос, чтобы использовать в качестве условия новое поле COL_NEW, и проблема исчезла.

Хотя я счастлив, что проблема ушла, я не могу объяснить это себе. Почему исполнение было медленным, если это не имело никакого отношения к NULL?

ОБНОВЛЕНИЕ: Похоже, что проблема возникла из-за плана кешированных запросов. Итак, вопрос в основном становится, как заставить обновить план запроса?

UPDATE: Несмотря на то, что ALTER TABLE может обновить план выполнения, проблема вернулась. Как я могу узнать, что происходит?

+0

Не могли бы вы разместить план выполнения запроса? НАПРИМЕР. 'SET SHOWPLAN_ALL ON идти --My SQL Query перейти SET SHOWPLAN_ALL OFF gO' –

ответ

0

Похоже, что ваш план запроса получил кеширование, в то время как статистика для нового столбца показала, что он полностью заполнен нулями, заставляя сканирование таблицы. После ALTER TABLE план запроса был обновлен, повторное повторное сканирование таблицы с помощью индексного lookujp, и производительность вернулась к нормальной.

Единственный способ узнать наверняка, если это то, что произошло, - это изучить планы запросов для обоих запросов, но они уже давно исчезли.

+0

Вы говорите, давно нет, я говорю резервное копирование :) Но я не понимаю, что я должен делать по-другому в следующий раз, когда я хочу добавить столбец в таблицу и получить много NULL? – greener

+0

Сканирование таблицы - это когда запрос начинается с записи 1 из стробированного индекса и сканирует все записи до конца индекса кластеризации. Индексный поиск заключается в том, когда запрос переходит в индекс для требуемого первого запроса и выполняется через индекс только до тех пор, пока он не будет прочитан все записи, необходимые для запроса. SQL Server usuall выполнит таблицу san, если она оценит, что> 10% записей таблицы должны быть прочитаны. Планы запросов кэшируются и не регистрируются, поэтому резервная копия не будет извлекать старый. –

+0

То, что я имел в виду под резервным копированием, было AMS AWS в неудовлетворительном состоянии. – greener