Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Имеем :
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (X64) Jul 9 2008 14:17:44 Copyright (c) 1988-2008 Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)


имею желание написать запрос следующего вида :

declare @bdate as int
declare @edate as int
declare @needorg as binary(8)

set @bdate=dbo.datetoint('20111001') -- Дата хранится с int-е
set @edate=dbo.datetoint('20111031')

set @needorg=(select nrec from katorg where name='ООО "Рога и Копыта"')

запрос :
-------------
select spo.nrec
from sporder spo inner join sklorder skl on spo.csklorder=skl.nrec and spo.sp=0 and spo.dord>=@bdate and spo.dord<=@edate
inner join katparty party on spo.cparty = party.nrec and party.CORGPAR=@needorg
inner join katpodr podrord on spo.ccpodr=podrord.nrec
inner join grpodr grpodr on podrord.cgrpodr = grpodr.nrec
---------
выполняется в районе 2 минут

а если без последнего :
inner join grpodr grpodr on podrord.cgrpodr = grpodr.nrec
или в варианте
left join grpodr grpodr on podrord.cgrpodr = grpodr.nrec

то получается примерно такой же набор данных за 7-9 секунд

Даже не знаю что еще добавить ,пожалуй вот это:

(select COUNT(*) from sporder)~10,5 млн записей
(select COUNT(*) from katparty)~700 тыщ записей
(select COUNT(*) from grpodr)~18 записей :)

как так inner join на таблу с 18 рекордами тормозит так выборку ?
28 мар 12, 20:28    [12329958]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
bormental
как так inner join на таблу с 18 рекордами тормозит так выборку ?
Ответ, как всегда, в плане выполнения.
28 мар 12, 20:32    [12329974]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31965
bormental
как так inner join на таблу с 18 рекордами тормозит так выборку ?
Да, странно...

Планы нужно смотреть, сравнивать.

Да, там просто select spo.nrec, нету слова TOP?
28 мар 12, 20:32    [12329977]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
Критик
Member

Откуда: Москва / Калуга
Сообщений: 35388
Блог
1) установить SP
2) где хороший план, где плохой?
3) если в конец запроса добавить OPTION (RECOMPILE), то ускорится?
28 мар 12, 20:33    [12329978]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
alexeyvg
Да, там просто select spo.nrec, нету слова TOP?


нету
28 мар 12, 20:34    [12329983]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
bad plan
  |--Parallelism(Gather Streams)
       |--Nested Loops(Inner Join, OUTER REFERENCES:([spo].[F$CSKLORDER], [Expr1024]) WITH UNORDERED PREFETCH)
            |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000], [Expr1023]) OPTIMIZED WITH UNORDERED PREFETCH)
            |    |--Compute Scalar(DEFINE:([Expr1022]=BmkToPage([Bmk1000])))
            |    |    |--Hash Match(Inner Join, HASH:([Bmk1000])=([Bmk1000]), RESIDUAL:([Bmk1000] = [Bmk1000]))
            |    |         |--Parallelism(Distribute Streams, Broadcast Partitioning)
            |    |         |    |--Hash Match(Inner Join, HASH:([podrord].[F$NREC])=([spo].[F$CCPODR]), RESIDUAL:([GAL810].[dbo].[T$SPORDER].[F$CCPODR] as [spo].[F$CCPODR]=[GAL810].[dbo].[T$KATPODR].[F$NREC] as [podrord].[F$NREC]))
            |    |         |         |--Parallelism(Gather Streams)
            |    |         |         |    |--Nested Loops(Inner Join, OUTER REFERENCES:([grpodr].[F$NREC]))
            |    |         |         |         |--Parallelism(Distribute Streams, RoundRobin Partitioning)
            |    |         |         |         |    |--Index Scan(OBJECT:([GAL810].[dbo].[T$GRPODR].[T$GRPODR3] AS [grpodr]))
            |    |         |         |         |--Index Seek(OBJECT:([GAL810].[dbo].[T$KATPODR].[T$KATPODR13] AS [podrord]), SEEK:([podrord].[F$CGRPODR]=[GAL810].[dbo].[T$GRPODR].[F$NREC] as [grpodr].[F$NREC]) ORDERED FORWARD)
            |    |         |         |--Index Seek(OBJECT:([GAL810].[dbo].[T$SPORDER].[T$SPORDER7] AS [spo]), SEEK:([spo].[F$SP]=(0)) ORDERED FORWARD)
            |    |         |--Nested Loops(Inner Join, OUTER REFERENCES:([party].[F$NREC], [Expr1020]) WITH UNORDERED PREFETCH)
            |    |              |--Index Seek(OBJECT:([GAL810].[dbo].[T$KATPARTY].[T$KATPARTY10] AS [party]), SEEK:([party].[F$CORGPAR]=[@needorg]) ORDERED FORWARD)
            |    |              |--Index Seek(OBJECT:([GAL810].[dbo].[T$SPORDER].[T$SPORDER19] AS [spo]), SEEK:([spo].[F$CPARTY]=[GAL810].[dbo].[T$KATPARTY].[F$NREC] as [party].[F$NREC]) ORDERED FORWARD)
            |    |--RID Lookup(OBJECT:([GAL810].[dbo].[T$SPORDER] AS [spo]), SEEK:([Bmk1000]=[Bmk1000]),  WHERE:([GAL810].[dbo].[T$SPORDER].[F$DORD] as [spo].[F$DORD]>=[@bdate] AND [GAL810].[dbo].[T$SPORDER].[F$DORD] as [spo].[F$DORD]<=[@edate]) LOOKUP ORDERED FORWARD)
            |--Index Seek(OBJECT:([GAL810].[dbo].[T$SKLORDER].[T$SKLORDER0] AS [skl]), SEEK:([skl].[F$NREC]=[GAL810].[dbo].[T$SPORDER].[F$CSKLORDER] as [spo].[F$CSKLORDER]) ORDERED FORWARD)


goodplan
  |--Parallelism(Gather Streams)
       |--Hash Match(Inner Join, HASH:([spo].[F$CSKLORDER])=([skl].[F$NREC]), RESIDUAL:([GAL810].[dbo].[T$SPORDER].[F$CSKLORDER] as [spo].[F$CSKLORDER]=[GAL810].[dbo].[T$SKLORDER].[F$NREC] as [skl].[F$NREC]))
            |--Bitmap(HASH:([spo].[F$CSKLORDER]), DEFINE:([Bitmap1022]))
            |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([spo].[F$CSKLORDER]))
            |         |--Hash Match(Inner Join, HASH:([podrord].[F$NREC])=([spo].[F$CCPODR]), RESIDUAL:([GAL810].[dbo].[T$SPORDER].[F$CCPODR] as [spo].[F$CCPODR]=[GAL810].[dbo].[T$KATPODR].[F$NREC] as [podrord].[F$NREC]))
            |              |--Bitmap(HASH:([podrord].[F$NREC]), DEFINE:([Bitmap1021]))
            |              |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([podrord].[F$NREC]))
            |              |         |--Index Scan(OBJECT:([GAL810].[dbo].[T$KATPODR].[T$KATPODR0] AS [podrord]))
            |              |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([spo].[F$CCPODR]), WHERE:(PROBE([Bitmap1021],[GAL810].[dbo].[T$SPORDER].[F$CCPODR] as [spo].[F$CCPODR])))
            |                   |--Hash Match(Inner Join, HASH:([party].[F$NREC])=([spo].[F$CPARTY]), RESIDUAL:([GAL810].[dbo].[T$SPORDER].[F$CPARTY] as [spo].[F$CPARTY]=[GAL810].[dbo].[T$KATPARTY].[F$NREC] as [party].[F$NREC]))
            |                        |--Bitmap(HASH:([party].[F$NREC]), DEFINE:([Opt_Bitmap1015]))
            |                        |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([party].[F$NREC]))
            |                        |         |--Index Seek(OBJECT:([GAL810].[dbo].[T$KATPARTY].[T$KATPARTY10] AS [party]), SEEK:([party].[F$CORGPAR]=[@needorg]) ORDERED FORWARD)
            |                        |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([spo].[F$CPARTY]))
            |                             |--Hash Match(Inner Join, HASH:([Bmk1000])=([Bmk1000]), RESIDUAL:([Bmk1000] = [Bmk1000]))
            |                                  |--Bitmap(HASH:([Bmk1000]), DEFINE:([Bitmap1020]))
            |                                  |    |--Hash Match(Inner Join, HASH:([Bmk1000])=([Bmk1000]), RESIDUAL:([Bmk1000] = [Bmk1000]))
            |                                  |         |--Bitmap(HASH:([Bmk1000]), DEFINE:([Bitmap1019]))
            |                                  |         |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([Bmk1000]))
            |                                  |         |         |--Index Seek(OBJECT:([GAL810].[dbo].[T$SPORDER].[T$SPORDER26] AS [spo]), SEEK:([spo].[F$SP]=(0)),  WHERE:([GAL810].[dbo].[T$SPORDER].[F$DORD] as [spo].[F$DORD]>=[@bdate] AND [GAL810].[dbo].[T$SPORDER].[F$DORD] as [spo].[F$DORD]<=[@edate] AND PROBE([Opt_Bitmap1015],[GAL810].[dbo].[T$SPORDER].[F$CPARTY] as [spo].[F$CPARTY])) ORDERED FORWARD)
            |                                  |         |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([Bmk1000]))
            |                                  |              |--Parallelism(Distribute Streams, RoundRobin Partitioning)
            |                                  |                   |--Index Seek(OBJECT:([GAL810].[dbo].[T$SPORDER].[T$SPORDER7] AS [spo]), SEEK:([spo].[F$SP]=(0)),  WHERE:([GAL810].[dbo].[T$SPORDER].[F$DORD] as [spo].[F$DORD]>=[@bdate] AND [GAL810].[dbo].[T$SPORDER].[F$DORD] as [spo].[F$DORD]<=[@edate] AND PROBE([Bitmap1019],[Bmk1000])) ORDERED FORWARD)
            |                                  |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([Bmk1000]))
            |                                       |--Index Scan(OBJECT:([GAL810].[dbo].[T$SPORDER].[T$SPORDER11] AS [spo]),  WHERE:(PROBE([Bitmap1020],[Bmk1000])))
            |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([skl].[F$NREC]))
                 |--Index Scan(OBJECT:([GAL810].[dbo].[T$SKLORDER].[T$SKLORDER0] AS [skl]),  WHERE:(PROBE([Bitmap1022],[GAL810].[dbo].[T$SKLORDER].[F$NREC] as [skl].[F$NREC])))
28 мар 12, 20:57    [12330046]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Критик
3) если в конец запроса добавить OPTION (RECOMPILE), то ускорится?


Да..сразу окейно становится
хезаешь эту опцию - и опять 2,5 минуты время выполнения )
28 мар 12, 21:02    [12330060]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
Критик
Member

Откуда: Москва / Калуга
Сообщений: 35388
Блог
bormental,

ознакомьтесь
http://www.sqlmag.com/article/sql-server/-using-the-recompile-query-hint-to-solve-parameter-sniffing-problems
29 мар 12, 14:25    [12333769]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Сегодня доработал select более менее полно как оно того треба и опять тормоз появился (
option (Recompile) не помогает более. Нашел вроде что тормозит выполнение. Наверное опять план нужно. В каком виде оптимально сюда его казать ? прикрепленным файлом или сюда скопипастить просто ? (он приличный получается по размеру ).
29 мар 12, 16:36    [12334924]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
bormental,

Выкладывайте действительный план, в виде xml, прикрепленным к сообщению архивом.
29 мар 12, 16:41    [12334968]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
SomewhereSomehow,

буду благодарен если подскажите как его в xml вывалить ? просто юзал тока SET SHOWPLAN_TEXT ON
29 мар 12, 16:45    [12334995]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
bormental,

set statistics xml on
либо ткните кнопку в SSMS - Include Actual Execution Plan
29 мар 12, 16:53    [12335059]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Собственно при хорошем плане отрабатывает в районе 15 секунд..при плохом где 6-7 минут

Хороший он становиться ,когда рубишь вот в этом месте :
....
on grnal.f$nrec = spgrnal.f$cgrnal and spgrnal.f$cnalog=@nalog and spgrnal.f$NALOG=@locstnal

последнее условие (and spgrnal.f$NALOG=@locstnal) :

on grnal.f$nrec = spgrnal.f$cgrnal and spgrnal.f$cnalog=@nalog --and spgrnal.f$NALOG=@locstnal


сразу становиться веселее ему как то ! в этом условии всего лишь передается ставка налога по которой "сужать" выборку.
Но сразу становиться с ней не гуд. Краем глаза успел тока увидеть что , сразу по mc происходит table scan вместо index seek
Пробовал указывать принудительно опции выборки по индексу (WITH (INDEX(t$katmc0))) - все равно скуль это игнорирует и делает почему то по своему

К сообщению приложен файл (troublesql.rar - 16Kb) cкачать
29 мар 12, 17:23    [12335340]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
saint
Member

Откуда: Архангельск
Сообщений: 2262
bormental,

статистики обновляли? часто неестественные тормоза вылезают из-за неверных статистик.
29 мар 12, 17:52    [12335572]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
saint
bormental,

статистики обновляли? часто неестественные тормоза вылезают из-за неверных статистик.


Это Вы об :

UPDATE STATISTICS ON < table_name > [ . <index_name> ]
WITH FULLSCAN {, NORECOMPUTE }

?
статистику почему сбрасывать нужно ?
29 мар 12, 17:57    [12335627]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
bormental,

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

Имхо, в "плохом" плане, основные томоза из-за оператора Table Spool, в этом операторе, сервер записывает в служебную таблицу аж 86 854 684 строк, после чего использует ее в соединении Nested Loops.

Есть предложение, попробовать переупорядочить соединения таблиц так, как они идут в "хорошем" плане, после этого для джойна с таблицей [GAL810].[dbo].[T$SPGRNAL] [spgrnal] прописать явный inner loop join, по идее, этот хинт должен заодно и форсировать порядок соединений, так что, есть вероятность получить план похожий на тот что вы именуете good.

Еще есть вероятность, что когда вы ставите option recompile, то сервер у вас прочухивает значение параметра @locstnal и т.к. для этого значения возвращается всего одна запись, он считает что нужно соединять таблицу одной из первых, после чего соединяет ее с t$katmc, при этом, эта ветка выполняется во внутреннем цикле соединения вложенными циклами и сервер начинает спулить в служебную таблицу. можно попробовать, дописать в option optimize for (@locstnal unknown).

Еще можно попробовать выдернуть результат выборки из этой таблицы во временную.

В общем, мне кажется, причина тормозов в этом спуле, а как от него избавиться - надо экспериментировать...
29 мар 12, 19:14    [12336130]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
SomewhereSomehow,

Проделал следующее. На тестовом сервере попробовал сделать на базе sp_updatestats и походу это как то повлияло. Запрос стал отрабатывать вполне хорошо (одинаково по времени и в моем первоначальном варианте и , с главным твоим предложением, использовать директиву inner loop join на узле t$spgrnal )


Что касается рабочего сервера, то да...тут использование вместо :

inner join t$spgrnal spgrnal on grnal.f$nrec = spgrnal.f$cgrnal and spgrnal.f$cnalog=@nalog

твоего варианта предложенного:
inner loop join t$spgrnal spgrnal on grnal.f$nrec = spgrnal.f$cgrnal and spgrnal.f$cnalog=@nalog

дает очень положительные моменты. Время выборки данных с 7 минут укладываетсся примерно в 20 секунд. При этом, походу, перекоеркивается весь план выполнения. Почему то даже по t$sporder (базовая таблица выборки ) происходит table scan , да и по t$katmc table scan тоже остается - но результаты улучшения более чем удовлетворяют.

Как только обратно ставлю вместо inner loop join просто inner join - то опять долгое выполнение получаю.

Я вообще не понимаю зачем так мудрит оптимизатор mssql . Логика же совсем простая от него требуется - взять по индексу кучу нужную из t$sporder (как базовой таблы выборки) и join-нить просто все к этим данным. По идее вроде просто все ) Но, наверное, я ошибаюсь что все так просто )

План новый хороший прилагаю

p.s. Да..БД галактическая, и как ты правильно, видимо из своего опыта, подметил - словарь трогать нельзя (по крайней мере ссыкотно очень). Так что приходиться оперировать только тем что имеем...хотя уже несколько лет есть возможность добавлять свои таблы в словарь, без последствий для работоспособности основного функционала системы (т.е. при этом не происходит пересчет контрольной суммы со всеми отсюда вытекающими...). А конечно любая правка стандартных таблиц системы (добавление своих полей, изменение существующих, добавление индексов, изменение сегментов существующих индекcов) - ну его нафиг )))

К сообщению приложен файл (New_Good_Plan.sqlplan - 115Kb) cкачать
29 мар 12, 21:07    [12336522]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
bormental
saint
bormental,

статистики обновляли? часто неестественные тормоза вылезают из-за неверных статистик.


Это Вы об :

UPDATE STATISTICS ON < table_name > [ . <index_name> ]
WITH FULLSCAN {, NORECOMPUTE }

?
статистику почему сбрасывать нужно ?


У вас явно поехавшая статистика на одной из этих 2-х таблиц. При чем это видно даже на "хорошем плане".

SELECT *
FROM t$katpodr podrord
  INNER JOIN t$grpodr grpodr on podrord.f$cgrpodr = grpodr.f$nrec

UPDATE STATISTICS t$katpodr WITH FULLSCAN
UPDATE STATISTICS t$grpodr WITH FULLSCAN
30 мар 12, 00:22    [12337246]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
bormental,

В новом плане все еще кривая статистика, как минимум на одном поле, причем sp_updatestats вас не спасет. Скорее всего дефолтного sample rate не хватает чтобы сделать хорошую статистику. Попробуйте выполнить вот это:

UPDATE STATISTICS t$sporder.f$cparty WITH FULLSCAN
UPDATE STATISTICS t$katparty.f$nrec WITH FULLSCAN
Ну и потом попробовать с хинтом и без. И новый план, интересно посмотреть :)
30 мар 12, 01:27    [12337382]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Mind
bormental,

В новом плане все еще кривая статистика, как минимум на одном поле, причем sp_updatestats вас не спасет. Скорее всего дефолтного sample rate не хватает чтобы сделать хорошую статистику. Попробуйте выполнить вот это:

UPDATE STATISTICS t$sporder.f$cparty WITH FULLSCAN
UPDATE STATISTICS t$katparty.f$nrec WITH FULLSCAN
Ну и потом попробовать с хинтом и без. И новый план, интересно посмотреть :)
30 мар 12, 07:21    [12337564]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Mind
bormental,

В новом плане все еще кривая статистика, как минимум на одном поле, причем sp_updatestats вас не спасет. Скорее всего дефолтного sample rate не хватает чтобы сделать хорошую статистику. Попробуйте выполнить вот это:

UPDATE STATISTICS t$sporder.f$cparty WITH FULLSCAN
UPDATE STATISTICS t$katparty.f$nrec WITH FULLSCAN
Ну и потом попробовать с хинтом и без. И новый план, интересно посмотреть :)



Mind, новый план "хороший" снял с сервера рабочего на котором не делал UPDATE STATISTICS (просто с inner loop join)
Через некоторое время, как доберусь до компиков, покажу план выполнения, оный получиться после выполнения Ваших инструкций.
А как Вы по плану видите что "в плане все еще кривая статистика" ?
30 мар 12, 07:24    [12337567]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
bormental
Mind
bormental,

В новом плане все еще кривая статистика, как минимум на одном поле, причем sp_updatestats вас не спасет. Скорее всего дефолтного sample rate не хватает чтобы сделать хорошую статистику. Попробуйте выполнить вот это:

UPDATE STATISTICS t$sporder.f$cparty WITH FULLSCAN
UPDATE STATISTICS t$katparty.f$nrec WITH FULLSCAN
Ну и потом попробовать с хинтом и без. И новый план, интересно посмотреть :)



Mind, новый план "хороший" снял с сервера рабочего на котором не делал UPDATE STATISTICS (просто с inner loop join)
Через некоторое время, как доберусь до компиков, покажу план выполнения, оный получиться после выполнения Ваших инструкций.
А как Вы по плану видите что "в плане все еще кривая статистика" ?


Нужно сравнивать Estimated rows vs Actual rows. Причем смотреть нужно начинать с правой верхней части плана, потому что ошибка постепенно накапливается и умножается. Если при первом джойне ошибка скажем 10 строк вместо 1 предполагаемой, то на следующем шаге это может быть уже 100К против 10К, что уже значительно. Идеальных оценок конечно все равно почти никогда не будет, ввиду несовершенства их мат. модели статистики, но если разница в тысычу или в 10 тысяч раз то это уже повод задуматься. Ну а напрямую от статистики зависят стоимости операторов, а от этого уже и пляшет весь план.

А смотреть на планы лучше вот этой замечательной бесплатной тулзой
SQL Sentry Plan Explorer
http://www.sqlsentry.com/plan-explorer/sql-server-query-view.asp
30 мар 12, 08:47    [12337703]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
bormental
SomewhereSomehow,

Проделал следующее. На тестовом сервере попробовал сделать на базе sp_updatestats и походу это как то повлияло. Запрос стал отрабатывать вполне хорошо (одинаково по времени и в моем первоначальном варианте и , с главным твоим предложением, использовать директиву inner loop join на узле t$spgrnal )


Что касается рабочего сервера, то да...тут использование вместо :

inner join t$spgrnal spgrnal on grnal.f$nrec = spgrnal.f$cgrnal and spgrnal.f$cnalog=@nalog

твоего варианта предложенного:
inner loop join t$spgrnal spgrnal on grnal.f$nrec = spgrnal.f$cgrnal and spgrnal.f$cnalog=@nalog

дает очень положительные моменты. Время выборки данных с 7 минут укладываетсся примерно в 20 секунд. При этом, походу, перекоеркивается весь план выполнения. Почему то даже по t$sporder (базовая таблица выборки ) происходит table scan , да и по t$katmc table scan тоже остается - но результаты улучшения более чем удовлетворяют.

Как только обратно ставлю вместо inner loop join просто inner join - то опять долгое выполнение получаю.

Я вообще не понимаю зачем так мудрит оптимизатор mssql . Логика же совсем простая от него требуется - взять по индексу кучу нужную из t$sporder (как базовой таблы выборки) и join-нить просто все к этим данным. По идее вроде просто все ) Но, наверное, я ошибаюсь что все так просто )

Так я же не просто предлагал воткнуть nested loop join, я еще предлагал поменять порядок соединения таблиц, на тот, который в первом плане, т.к. как только вы явно прописываете тип соединения, то у вас автоматически форсируется порядок соединений, в результате куча hash joins...
Однако, в свете того что вы сказали, про базовую таблицу, если логика такая, то может быть попробовать записать ту самую выборку во временную таблицу, повесить на нее индексы и в запросе уже использовать ее? и хинтовать ничего не придется...типа такого:
select spo.f$kol as kol
	  ,spo.f$srprice as spoprice
	  ,party.f$nrec as partynrec
      ,podrord.f$cgrpodr as cgrpodr
      ,skl.f$csopr as sklcspsopr
      ,spo.f$cmc as spocmc
      ,spo.f$vidorder vidorder
into #selspo
from t$sporder spo 
	inner join t$sklorder skl on spo.f$csklorder=skl.f$nrec and spo.f$sp=0 and spo.f$dord>=@bdate and spo.f$dord<=@edate
	inner join t$katparty party on spo.f$cparty = party.f$nrec and party.f$CORGPAR=@needorg
	inner join t$katpodr podrord on spo.f$ccpodr=podrord.f$nrec
	inner join #needpodr atri on spo.f$ccpodr=atri.f$crec and atri.f$vcomp in (@nreclevelo,@nreclevelp,@nreclevelu)

alter table #selspo add constraint PK_selspo primary key (...);
create index ix_partynrec on #selspo(partynrec);
create index ix_sklcspsopr on #selspo(sklcspsopr);
create index ix_spocmc on #selspo(spocmc);
30 мар 12, 08:56    [12337723]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
bormental
Member

Откуда:
Сообщений: 90
Mind
bormental,

В новом плане все еще кривая статистика, как минимум на одном поле, причем sp_updatestats вас не спасет. Скорее всего дефолтного sample rate не хватает чтобы сделать хорошую статистику. Попробуйте выполнить вот это:

UPDATE STATISTICS t$sporder.f$cparty WITH FULLSCAN
UPDATE STATISTICS t$katparty.f$nrec WITH FULLSCAN
Ну и потом попробовать с хинтом и без. И новый план, интересно посмотреть :)



развернул бак новый. Ничего не предпринимая запустил скрипт и он также выполнился в районе 7 минут ожидаемо.
далее запустил

UPDATE STATISTICS t$sporder WITH FULLSCAN
UPDATE STATISTICS t$katparty WITH FULLSCAN

UPDATE STATISTICS t$katpodr WITH FULLSCAN
UPDATE STATISTICS t$grpodr WITH FULLSCAN

после этого запустил тот же скрипт. Отработало где то за 3 минуты тоже самое. Но, каждый последующее выполнение уже делается меньше 30 секунд (менял параметры входящие специально...). Внесениие хинта inner loop join никак не влият после этого уже.
План новый прилагаю

К сообщению приложен файл (Good_Plan_after_updstat.sqlplan - 134Kb) cкачать
30 мар 12, 13:28    [12339935]     Ответить | Цитировать Сообщить модератору
 Re: Поясните поведение Sql при таком select  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
bormental,

я удивляюсь как с хинтом медленнее не стало, вы же просто его добавляете, игнорируя основную мысль, по поводу переупорядочивания соединений...
А с временной таблицей не пробовали?
30 мар 12, 13:48    [12340074]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить