Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Эффективность плана выполнения запроса [MSSQL]


Страницы:   1 2

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. поиграйся с настройками оптимизатора


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо