![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Эффективность плана выполнения запроса [MSSQL]
Bless © (2005-04-25 16:59:00)Проблема вот в чем.
В пятницу, после жалоб на жуткие тормоза, я посмотрел на план выполнения одного запроса (выборка)
(который эти тормоза провоцировал).
Оказалось, что этот план (сгенерированный самим MS SQL, там нет никаких хинтов) - на редкость неудачный.
Потанцевав немного с бубном, решил перегрузить сервер. После перезагрузки сделал заодно полный BACKUP базы.
Это (перезагрузка) не помогло. Но тут к счастью вскоре закончился рабочий день. :)
В понедельник же тормозов - как и не бывало. Посмотрел на план выполнения - он стал совсем другим!
Я из сделанного накануне backup-а сделал себе тестовую копию базы данных.
И выполнил в ней этот же запрос. В результате - те же тормоза и тот же фиговый план выполнения, что и в пятницу.
Чем это можно объяснить?
Bless (2005-04-27 09:50:00) [21]Nikolay M. © (26.04.05 18:40) [14]>
Что касается индексов, то все есть. Ведь в этой же базе, ничего не меняя, в понедельник все заработало. И на JOIN я тоже уже менял.
Безрезультатно.
Nikolay M. (2005-04-26 18:40:00) [22]
> Попробовал. План ничуть не изменился :(
Ну, ладно, все равно дело не в этом. В любом случае у тебя встречается в плане как минимум один скан таблицы, что не есть гуд для достаточно больших таблиц. Проверь наличие индексов по связываемым полям. IN замени на EXISTS или вообще на JOIN.
Bless (2005-04-26 18:00:00) [23]Nikolay M.[12]>
Попробовал. План ничуть не изменился :(
Nikolay M. (2005-04-26 17:41:00) [24]Кстати, попробуй ради эксперимента заменить переменные @nzs и @comp на собственно их значения. Думаю, план должен поменяться.
Bless (2005-04-26 17:20:00) [25]Кстати, статистика хоть и появилось, но план выполнения остался прежним :(
Bless (2005-04-26 16:55:00) [26]Неужели MSSQL, когда автоматически обновляет статистику индексов, тоже вызвает DBCC DBREINDEX?
Bless (2005-04-26 16:52:00) [27]Статистика наконец-то появилась
После вызова DBCC DBREINDEX (pozib_m).
Это не странно?
Или sp_updatestats работает только для как бы это сказать "настоящих статистик", у которых есть свое имя, а для статистик, положенных индексу, не работает?
Nikolay M. (2005-04-26 13:31:00) [28]
> Bless © (26.04.05 12:54) [7]
Для начала в БОЛ. Ключевые слова для поиска ты уже знаешь.
Потом за нюансами сюда:
http://www.sql.ru/forum/actualtopics.aspx?search=%F1%F2%E0%F2%E8%F1%F2%E8%EA%E0&bid=1
Bless (2005-04-26 12:54:00) [29]Nikolay M.[6]>
Ну нифига себе! Сделал, как ты сказал. Оказалось, что статистики по индексам таблицы pozib_m в "плохой" базе вообще нет!
То есть поле sysindexes.statblob = NULL.
Почему sp_updatestats не обновила статистику для этой таблицы?
Как сделать, чтоб статистика по индексам этой таблицы обновилась?
И почему она могла пропасть? Это я что-то где-то "ровными" руками потрогал?
Киньте, кто знает, толковым урлом в меня на эту тему, а то я с понятием "статистика" только в пятницу после этой проблемы познакомился и мое представление о ней пока очень смутное.
Nikolay M. (2005-04-26 10:17:00) [30]
> >Необновленной статистикой.
>
> Я тоже так подумал. Но вызов sp_updatestats (этого ведь
> достаточно чтобы обновить статистику? Или нет?) ничего не
> изменил.
Сделай для нужного индекса
DBCC SHOW_STATISTICS
и посмотри, сколько записей (Rows Sampled) от общего числа записей (Rows) на данный момент учтено последним обновлением статистики.
sp_updatestats собирает статистику по дефолтному кол-ву записей, чему оно равно в твоем случае - хз, но, скорее всего, не 100%.
Bless (2005-04-26 10:01:00) [31]>Необновленной статистикой.
Я тоже так подумал. Но вызов sp_updatestats (этого ведь достаточно чтобы обновить статистику? Или нет?) ничего не изменил.
MOA [4]>
Не помогло. Тем более, что я выполняю этот запрос не в процедуре а просто в Query Analizer-е.
Запрос выглядит так:
SELECT nzz INTO #p
FROM pozib WHERE nzs=@nzs --вернет 91 запись.
/*ниже источник тормозов*/
SELECT * FROM pozib_m pm
INNER JOIN shapb_m_cache s ON pm.nzm=s.nzm
WHERE s.nzs=@nzs AND s.comp_name=@comp AND s.indi<>1
AND pm.nzp IN (SELECT nzz FROM #p) AND s.del<>1
Неэффективный план запроса выглядит так:
1) table scan
OBJECT: ([v_ao].[dbo].[Pozib_m] AS [pm])
На выходе - 613 444записи (то есть все записи в этой таблице)
2) table scan
OBJECT: ([v_ao].[dbo].[shapb_m_cache] AS [s])
WHERE: ((([s].[nzs]=[@nzs] AND [s].[indi]<>1) AND [s].[comp_name]=[@comp_name]) AND Convert([s].[del])<>1)
На выходе 21 запись.
3) Hash Match/Inner joinпервого и второго пунктов
HASH : ([pm].[nzm]=[s].[nzm])
На выходе 25 685записей
4) table scan
OBJECT : [tembdb][dbo][ #p_________________000000000830]
На выходе 91 запись
5) Hash Match/Inner join
HASH : [pm].[nzp]=[ #p].[nzz]
На выходе 113 результирующих записей.
А эффективный начинается так :
1) table scan
OBJECT : [tembdb][dbo][ #p_________________000000000830]
На выходе 91 запись
2) Sort/ Distinct Sort
DISTINCT ORDER BY : ([ #p].[nzz] ASC)
3) Index Seek
OBJECT : ([ao].[dbo].[pozib_m].[pozib_m_nzp_index] AS [pm]),
SEEK : ([pm].[nzp]=[ #p].[nzz]) ORDERERD FORWARD
На выходе 168 записей.
Потом эти 168 объединяются с 21 записью из shapb_m_cache и т.д.
То есть в дальнейшем работа ведется уже с маленькими наборами данных.
Если вручную слегка изменить запрос на
SELECT * FROM pozib_m pm WITH (INDEX pozib_m_nzp_index)
INNER JOIN shapb_m_cache s ON pm.nzm=s.nzm
WHERE s.nzs=@nzs AND s.comp_name=@comp AND s.indi<>1
AND pm.nzp IN (SELECT nzz FROM #p) AND s.del<>1
то это приводит лишь к тому, что в пункте 1) заменяется table scan на index seek, что без толку, поскольку возвращаются все те же 613 444 записей.
Как мне сделать из первого плана второй?
Если так:
SELECT * FROM #p
INNER JOIN pozib_m pm ON #p.nzz=pm.nzp
INNER JOIN shapb_m_cache s ON pm.nzm=s.nzm
WHERE s.nzs=@nzs AND s.comp_name=@comp AND s.indi<>1 --stoimost trudozatrat (indi=1) schitaetsia, a ne vvoditsia polzovatelem
AND s.del<>1
OPTION (FORCE ORDER)
то получается почти так же эффективно, как и в случае второго плана выполнения (по времени), хотя немножко все же хуже. Да и план выполнения все ж отличается от эффективного.
План начинается так:
1) table scan
OBJECT : [tembdb][dbo][ #p_________________000000000830]
На выходе 91 запись
2) table scan
OBJECT: ([v_ao].[dbo].[Pozib_m] AS [pm])
На выходе - все те же 613 444записи.
3) Hash Match/Inner join
HASH : ([ #p].[nzz]=[pm].[nzp])
На выходе 168 записей. Как и в эффективном плане после 3) пункта. Хотя и пришли к этим 168 записям по-разному.
Но что-то мне очень не охота хинты в запрос вставлять.
MOA (2005-04-25 22:48:00) [32]DBCC FREEPROCCACHE
Johnmen (2005-04-25 22:02:00) [33]>Чем это можно объяснить?
Глобальным потеплением.
Nikolay M. (2005-04-25 21:31:00) [34]
> Чем это можно объяснить?
Необновленной статистикой.
Desdechado (2005-04-25 17:29:00) [35]1. сборку статистики индексов сделай
2. поиграйся с настройками оптимизатора