Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 анализ производительности запроса  [new]
Eugene_p1
Member

Откуда: Москва
Сообщений: 295
Коллеги, подскажите пожалуйста,

--Table1
CREATE TABLE [dbo].[Table1]
(
	[VCode] [int] NOT NULL,
	[PCode] [int] NULL,
	[Name] [varchar](255) NOT NULL,
	[rowguid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
	[b_data] [smalldatetime] NULL,
	[e_data] [smalldatetime] NULL,
	[ToDelete] [int] NULL,
 CONSTRAINT [PK__Table1__VCode__610] PRIMARY KEY CLUSTERED 
(
	[VCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]

-- Raw_Data
CREATE TABLE #raw_data
(int1 int, 
statcode char(6), 
taxCode varchar(3), 
regCode char(2), 
deban int, 
form_type nchar(3), 
cat nvarchar(12),
clmn varchar(100), 
value float)


Если в плане запроса Clustered Index Seek (по PK) = 53% (Estimated Operator Cost = 7.79 (53%)), о чем это может говорить?

Prefix: [dbo].[table1].VCode = Scalar Operator([tempdb].[dbo].[#raw_data].[deban] as [a].[deban])

В запросе:
LEFT OUTER JOIN (SELECT vcode, name as cName FROM dbo.table1 (nolock)) c ON c.vcode = a.deban 

Оба поля int
Почему там Scalar Operator?
Actual Number of Executions = Actual Number of Rows = 48575, т.е. какое-то вычисление для каждой строки.



Может быть связано с тем, что при создании таблицы #raw_data для deban не указано NOT NULL ?
2 сен 13, 16:14    [14785134]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Eugene_p1
Member

Откуда: Москва
Сообщений: 295
Выясняется, что на самом деле
LEFT OUTER JOIN (SELECT vcode, name as cName FROM dbo.view1 (nolock)) c ON c.vcode = a.deban 


А внутри view:
SELECT
vcode, name, pcode, b_data, e_data
FROM dbo.Table1
WHERE ToDelete IS NULL


Не понятно, почему
Prefix: [dbo].[table1].VCode = Scalar Operator([tempdb].[dbo].[#raw_data].[deban] as [a].[deban])
2 сен 13, 19:05    [14786281]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31965
Eugene_p1
Может быть связано с тем, что при создании таблицы #raw_data для deban не указано NOT NULL ?
Нет, не зависит.

Думаю, просто стандартное обозначение, получение поля...
2 сен 13, 21:00    [14786668]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

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

Непонятно, почему тема называется анализ производительности, что анализировать?
Нет сформулированной проблемы производительности "что-то медленно, что-то быстро, вот планы и т.д."

Скорее вопрос продиктован любопытством, (наверное потому что это напоминает применение функции над полем?)

Скалярный оператор
Скалярный оператор это (как ни странно) применение скалярного оператора над другим оператором.
+ терминология оператора в данном контексте

Тут может быть путаница терминов, говоря о производительности, подразумевается контекст планов, в плане, оператором принято называть графический узел плана, представляющий какой-либо логический или физический оператор. Я имею ввиду оператор внутри сиквела, например, выделенная часть выражения:
"where a = 1"
представляется серверу как:
ScaOp_Comp x_cmpEq
        ScaOp_Identifier QCOL: [t1].a
        ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=1)

Скалярный оператор "равно" над
     Скалярный оператор идентификатор колонки [t1].a
     Скалярный оператор константа значения 1

(года полтора назад описывал у себя в блоге подробнее Оптимизатор (ч.1): Введение, Optimization: Simplification)


Само по себе, применение абстрактного скалярного оператора ни хорошо, ни плохо, и ни о чем не говорит, кроме того, что в сиквеле есть такие абстракции, и оно так работает. Лучше смотрите на детали оператора, детали скрыты в XML, открывайте план как XML и смотрите.
create function dbo.f (@a int) 
returns int
as begin return @a; end 
go
declare @t1 table (a int primary key, b varchar(10) unique);
declare @t2 table (a int primary key, b varchar(10) unique);

set statistics xml on;
select * from @t1 t1 where a = 1; --1
select * from @t1 t1 where b like 'a'; --2
select * from @t1 t1 join @t2 t2 on t1.a = t2.a; --3
select count(*) from @t1 group by a; --4
select dbo.f(a) from @t1; --5
set statistics xml off;
go
drop function dbo.f;
go

+
-- 1. Seek Keys[1]: Prefix: @t1.a = Scalar Operator((1))
<ScalarOperator ScalarString="(1)">
	<Const ConstValue="(1)" />
</ScalarOperator>

--2. @t1.[b] as [t1].[b] like 'a'
<ScalarOperator ScalarString="@t1.[b] as [t1].[b] like 'a'">
	<Intrinsic FunctionName="like">
		<ScalarOperator>
			<Identifier>
				<ColumnReference Table="@t1" Alias="[t1]" Column="b" />
			</Identifier>
		</ScalarOperator>
		<ScalarOperator>
			<Const ConstValue="'a'" />
		</ScalarOperator>
	</Intrinsic>
</ScalarOperator>

--3. @t1.[a] as [t1].[a] (примерно как у вас, просто представляет скаляр в колонке t1.a
<ScalarOperator ScalarString="@t1.[a] as [t1].[a]">
	<Identifier>
		<ColumnReference Table="@t1" Alias="[t1]" Column="a" />
	</Identifier>
</ScalarOperator>

--4. [Expr1003] = Scalar Operator(CASE WHEN (0) IS NULL THEN (0) ELSE (1) END)
<ScalarOperator ScalarString="CASE WHEN (0) IS NULL THEN (0) ELSE (1) END">
    <IF>
    <Condition>
        <ScalarOperator>
        <Logical Operation="IS NULL">
            <ScalarOperator>
				<Const ConstValue="(0)" />
            </ScalarOperator>
        </Logical>
        </ScalarOperator>
    </Condition>
    <Then>
        <ScalarOperator>
			<Const ConstValue="(0)" />
        </ScalarOperator>
    </Then>
    <Else>
        <ScalarOperator>
			<Const ConstValue="(1)" />
        </ScalarOperator>
    </Else>
    </IF>
</ScalarOperator>

--5. [Expr1003] = Scalar Operator([master].[dbo].[f]([a]))
<ScalarOperator ScalarString="[master].[dbo].[f]([a])">
    <UserDefinedFunction FunctionName="[master].[dbo].[f]">
    <ScalarOperator>
        <Identifier>
	        <ColumnReference Column="a" />
        </Identifier>
    </ScalarOperator>
    </UserDefinedFunction>
</ScalarOperator>



Потенциальные проблемы
Самый известный, потенциально проблемный оператор, к счастью, отображается в графических свойствах в плане (еще и Warning красным цветом дается!):
declare @t1 table (a int primary key, b varchar(10) unique);
declare @t2 table (a int primary key, b varchar(10) unique);
set statistics xml on;
select * from @t1 t1 join @t2 t2 on t1.a = t2.b; --6
set statistics xml off;

Картинка с другого сайта.


Но есть такие, которые могут влиять на производительность, но в деталях графического плана, не отображаются (почему?..)
set statistics xml on;
declare @t3 table (d datetime primary key)
select * from @t3 where convert(date,d) = '2010-01-01';
set statistics xml off;

Картинка с другого сайта.


Что такое Expr1005 и Expr1006? В свойствах Compute Scalar этого тоже нет.
Неясно, до тех пор, пока не посмотришь в XML:
>>>                        <ScalarOperator ScalarString="GetRangeThroughConvert('2010-01-01','2010-01-01',(62))">
>>>                          <Intrinsic FunctionName="GetRangeThroughConvert">
                            <ScalarOperator>
                              <Const ConstValue="'2010-01-01'" />
                            </ScalarOperator>
                            <ScalarOperator>
                              <Const ConstValue="'2010-01-01'" />
                            </ScalarOperator>
                            <ScalarOperator>
                              <Const ConstValue="(62)" />
                            </ScalarOperator>
                          </Intrinsic>
                        </ScalarOperator>

Как такой оператор может влиять на производительность, реальный пример, читать тут:
sql.ru: В каких случаях опатимизатор может не использовать статистику?
Подробнее читать тут: Dynamic Seeks and Hidden Implicit Conversions

Подытоживая
Виновато ли тут отображение самого факта скалярного сравнения? Скорее нет, важны детали и что с чем сравнивается. Сам по себе скалярный оператор не несет ничего плохого, это то как работает и то как отображается. Если возникают сомнения, проверьте детали в XML, проверьте операнды и выражения.

П.С.
Ну и до тех пор, пока
автор
Actual Number of Executions = Actual Number of Rows = 48575

Беспокоиться о плане не зачем.
Если, кончено, только не возникли реальные проблемы в производительности. Например, у меня вот только сегодня на работе подвернулся интересный случай, и вроде план подозрений не вызывает и оценки ок - а работает медленно, пока не посмотрел как распределяются строки по потокам, и не увидел процессорное vs общее время + ожидания - было непонятно. Это я к тому, что анализ производительности лучше всегда делать исходя из реалий а не абстракций.
Но ваше любопытство понятно и это стремление я разделяю =)
3 сен 13, 01:02    [14787228]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
SomewhereSomehow
Ну и до тех пор, пока
автор
Actual Number of Executions = Actual Number of Rows = 48575

Беспокоиться о плане не зачем.

Кстати, пардон, прочитал то, что мой глаз хотел прочитать, прочитал как "Estimated Number of Rows = Actual Number of Rows = 48575"
Если это так, то не переживайте. Если это не так - не спешите винить на Scalar Operator(...), пока не проверите детали оператора.
Далее по результатам проверки.
3 сен 13, 01:55    [14787250]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Eugene_p1
Member

Откуда: Москва
Сообщений: 295
SomewhereSomehow,

Спасибо большое!

Читаю и изучаю блог.

Изучаю план в XML. Будут вопросы - напишу здесь.
3 сен 13, 16:36    [14790257]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Eugene_p1
Member

Откуда: Москва
Сообщений: 295
Столкнулся с очень интересным эффектом.

Немного разверну, что я писал. В запросе было:

SELECT .....
FROM #raw_data a
	LEFT OUTER JOIN @ref_Taxes r ON a.taxCode = r.ref_taxCode 
	LEFT OUTER JOIN (SELECT vcode, name as cName FROM dbo.table1 (nolock)) c ON c.vcode = a.deban 


Без WHERE.

Когда я табличную переменную заменил на временную таблицу, Clustered Index Seek по Table1 с 29% уменьшился до обычных 8%.

В связи с этим вопрос к гуру - почему?
4 сен 13, 15:35    [14794810]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

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

Любой вопрос по производительности должен быть сопровожден репро или планом с информацией о структуре таблиц и индексов (совсем хорошо, если статистикой). Тогда можно рассчитывать на более менее конкретный ответ (и то не всегда, т.к. лучше один раз пощупать, чем сто раз увидеть). Иначе, получается обсуждение сферических коней в вакууме и чистая теория.

Но раз вы спрашиваете без конкретики, то и я отвечу чисто теоретически, т.к. не знаю что у вас там реально.

Как известно, оптимизатор опирается на такое понятие как стоимость, исходя из стоимости он решает какой итератор использовать, выбирая наиболее дешевый. Стоимость измеряется в неких условных единицах, пусть будут попугаи.

В основе оценки стоимости лежат оценки, поскольку это оценки и сделаны до выполнения, они могут быть далеки от реальности. Например, табличные переменные не имеют статистики и количество строк в них предполагается равным одной строке. Временные таблицы имеют статистику и имеют информацию о количестве строк (правда, со своими нюансами).

Теперь представьте, доступ к одной строке стоит "один попугай".

1) Табличная переменная:
Вы соединяете три таблицы, таблицу 1, табличную переменную и таблицу 2 именно в таком порядке. Известно, что в таблице 1 - 100 строк, сканировать ее - "100 попугаев". В табличной переменной неизвестно сколько строк (до момента выполнения, т.е. в момент компиляции плана - неизвестно), предполагаем что одна, и т.к. нет статистики и неизвестно что там за строки, предполагаем, что эта одна строка теоретически может соединиться со всеми строками таблицы 1. Итак соединение таблицы 1 и табличной переменной - 100 строк. Теперь, соединяем таблицу 2, допустим в ней 1000 строк и из них нужно найти 100 совпадающих, т.е. как раз выполнить поиск 100 раз - тоже 100 попугаев. Всего 300 попугаев.

2) Временная таблица:
Опять три таблицы, таблица 1 -100 строк, но на этот раз известная статистика временной таблицы, там 10 строк. Т.к. статистика известна, количество строк известно, то известно что соединение таблицы 1 и временной таблицы дает 10 строк. Теперь, по таблице 2 нам нужно найти уже не 100 строк а 10 строк, итого, оценка: сканирование таблицы 1 - 100 попугаев, временной таблицы 10, таблицы 2 - 10.

Считаем проценты:
1) Три таблицы по 100 попугав всего 100+100+100 = 300, т.е. вес каждой операции примерно по 33%.
2) Три таблицы, всего 100+10+10 = 120, т.е. 83%, 8.35%, 8.35%.

Результат:
Для табличной переменной вес доступа (допустимо поиска) к таблице 2 уменьшился с 33% до 8.35%. Это очень грубая иллюстрация конечно, совсем не берется в расчет вся сложная модель оценки, соединения оцениваются по разному, поиск и просмотр по разному, и т.д. - но это иллюстрирует принцип.
Значит ли это что так все оно и будет в реальности? Нет! Просто точнее оценка.
Но чем точнее (ближе к истине) оценка тем лучше.

Я поленился придумывать реалистичный пример, по этому, просто иллюстрирую идею при помощи хинтов.
---------------------------------------
-- Script 1
dbcc freeproccache
go
use tempdb;
create table t1(a int primary key, b int);
create table t2(a int primary key);
insert t1 select top(100) number, number from master..spt_values where type = 'P' order by 1;
insert t2(a) select top(1000) number from master..spt_values where type = 'P' order by 1;
go
-- table @var
declare @t table(a int);
insert @t select top(200) number from master..spt_values where type = 'P' order by 1;
set statistics xml on
select t1.a,t.a,t2.a from
	t1 	
	left loop join @t t on t1.a = t.a
	left loop join t2 on t1.b = t2.a
set statistics xml off
go
-- table #temp
create table #t (a int);
insert #t select top(200) number from master..spt_values where type = 'P' order by 1;
set statistics xml on
select t1.a,t.a,t2.a from
	t1 	
	left loop join #t t on t1.a = t.a
	left loop join t2 on t1.b = t2.a
set statistics xml off
go
drop table t1,t2,#t;
go

Картинка с другого сайта.

Проценты очень сбивают с толку, когда неверно их интерпретируешь.

+ Напоследок, вам меленькая загадка, если хотите, конечно =)


---------------------------------------
-- Script 2
dbcc freeproccache
go
use tempdb;
create table t1(a int primary key, b int);
create table t2(a int primary key);
insert t1 select top(100) number, number from master..spt_values where type = 'P' order by 1;
insert t2(a) select top(1000) number from master..spt_values where type = 'P' order by 1;
-- table @var
declare @t table(a int, b int);
insert @t select top(200) number, number from master..spt_values where type = 'P' order by 1;
set statistics xml on
select t1.a,t.a,t2.a from
	t1 	
	left loop join @t t on t1.a = t.a
	left loop join t2 on t1.b = t2.a
set statistics xml off
go
-- table #temp
create table #t (a int);
insert #t select top(200) number from master..spt_values where type = 'P' order by 1;
set statistics xml on
select t1.a,t.a,t2.a from
	t1 	
	left loop join #t t on t1.a = t.a
	left loop join t2 on t1.b = t2.a
set statistics xml off
go
drop table t1,t2,#t;
go

Картинка с другого сайта.

Почему во втором скрипте для табличной переменной проценты другие?
5 сен 13, 00:08    [14796687]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
plombir86
Member

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

В Script2 оценка кардинальности на табличной переменной изменилось TableCardinality="200"

а вот почему это произошло? почему после добавления поля b, оптимизатор иначе оценивает кардинальность?
5 сен 13, 11:58    [14798474]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Гость333
Member

Откуда:
Сообщений: 3683
plombir86
В Script2 оценка кардинальности на табличной переменной изменилось TableCardinality="200"

Это, простите, вы где увидели?
5 сен 13, 12:06    [14798529]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
plombir86
Member

Откуда:
Сообщений: 15
Гость333,

Вывод плана в XML

<RelOp NodeId="3" PhysicalOp="Table Scan" LogicalOp="Table Scan" EstimateRows="200" EstimateIO="0.0032035" EstimateCPU="0.0002985" AvgRowSize="11" EstimatedTotalSubtreeCost="0.0330535" TableCardinality="200" Parallel="0" EstimateRebinds="0" EstimateRewinds="99">
5 сен 13, 12:11    [14798576]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Гость333
Member

Откуда:
Сообщений: 3683
plombir86
Гость333,

Вывод плана в XML

<RelOp NodeId="3" PhysicalOp="Table Scan" LogicalOp="Table Scan" EstimateRows="200" EstimateIO="0.0032035" EstimateCPU="0.0002985" AvgRowSize="11" EstimatedTotalSubtreeCost="0.0330535" TableCardinality="200" Parallel="0" EstimateRebinds="0" EstimateRewinds="99">

Хм. Действительно, это так для MSSQL 2012.

Для MSSQL 2008 R2 ожидаемое количество строк = 1:

<RelOp NodeId="3" PhysicalOp="Table Scan" LogicalOp="Table Scan" EstimateRows="1" EstimateIO="0.0032035" EstimateCPU="7.96e-005" AvgRowSize="11" EstimatedTotalSubtreeCost="0.0111635" TableCardinality="0" Parallel="0" EstimateRebinds="0" EstimateRewinds="99">

SomewhereSomehow, ваши комментарии? :-)
5 сен 13, 12:20    [14798661]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

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

А в 2008R2 вы полностью скрипт выполнили, включая начальный "dbcc freeproccache"?
Вообще это ж ТС загадка, вы сразу отгадаете =)
5 сен 13, 12:28    [14798756]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Гость333
Member

Откуда:
Сообщений: 3683
SomewhereSomehow
Гость333,

А в 2008R2 вы полностью скрипт выполнили, включая начальный "dbcc freeproccache"?

Да, действительно, мой промах :-)
Несомненно, эта команда была очень важна ;-)
5 сен 13, 12:48    [14798982]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Eugene_p1
Member

Откуда: Москва
Сообщений: 295
SomewhereSomehow
Гость333,
Вообще это ж ТС загадка, вы сразу отгадаете =)

Это как раз мой случай, а вот почему так происходит, могу только догадываться.

Исходя из того, что Вы написали, думаю, что оптимизатор оценивает кол-во строк в @t в 1, а на самом деле их оказывается больше - отсюда и более затратный поиск по индексу.
Либо, как вариант, происходит Seek по каждому конкретному значению, а не списку.

Если не прав - дайте наводку. :)
5 сен 13, 15:15    [14800318]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Eugene_p1
Member

Откуда: Москва
Сообщений: 295
А что означает Table Cardinality ?
5 сен 13, 15:16    [14800324]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Eugene_p1
А что означает Table Cardinality ?

Количество строк в таблице.
5 сен 13, 15:20    [14800352]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
чч
Guest
SomewhereSomehow,

а почему при добавлении одной колонки в табличную переменную, оптимизатор сразу же меняет оценку Estimated number of Rows?
Да еще и делает это правильно.
5 сен 13, 15:45    [14800508]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
чч
Guest
dbcc freeproccache
go
use tempdb;
create table t1(a int primary key, b int);
create table t2(a int primary key);
insert t1 select top(100) number, number from master..spt_values where type = 'P' order by 1;
insert t2(a) select top(1000) number from master..spt_values where type = 'P' order by 1;
-- table @var
declare @t table(a int, c int);
insert @t select top(200) number, number from master..spt_values where type = 'P' order by 1;
set statistics xml on
select t1.a,t.a--,t2.a 
from
	t1 	
	left loop join @t t on t1.a = t.a
	
	select * from @t t
	left loop join t1 on t.a = t1.a 
set statistics xml off


Еще интересное, почему в первом случае оптимизатор для кластерного индекса таблицы t1 ожидает 100 записей, а для табличной переменной одну
А во втором случае оптимизатор ожидает 200 записей для табличной переменной и только одну по кластерному индексу таблицы t1.
Почему?
5 сен 13, 16:00    [14800595]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
kalimba
Member

Откуда:
Сообщений: 297
Присоединяюсь, тоже не понял в чем магия. "Дэвид Блейн, в рот мне ноги, раскукожь меня обратно!"
5 сен 13, 16:43    [14800906]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Колонка, это отвлекающий маневр =)
Все дело в рекомпиляции. Тот же эффект если добавить option(recompile) в запрос с табличной переменной.
Если приглядеться, в первом скрипте между созданием таблиц t1, t2 и запросом с табличной переменной - стоит разделитель пакетов инструкций (батчей) GO.

План для батча компилируется целиком, для всех инструкций, после того как план скомпилирован, начинается выполнение инструкций батча. Но если запрос приходит на сервер в едином пакете с инструкциями по созданию таблиц, то инструкции содержащие ссылки на еще не существующий таблицы не могут быть скомпилированы, пока эти таблицы не будут созданы. Проще говоря, план не может ссылаться на еще не существующие таблицы. По этому компиляция откладывается "Defered compile" и начинается выполнение.

Когда таблицы созданы, и выполнение доходит до запроса компиляция которого была отложена, происходит - рекомпиляция (компиляция считается рекомпиляцией, если происходит во время выполнения). Оптимизатор прослушивает число строк в таблице, как он делал бы это с option(recompile), но т.к. статистики на табличной переменной по прежнему нет, то хоть число строк и известно - оценка все-равно получается немного другая, по сравнению со временной таблицей.

Все счастливы, за исключением того, кого это может сбить, особенно во время проведения экспериментов над оптимизатором. Я и сам иногда забываю про это, удивляюсь, но быстро вспоминаю про рекомпиляцию.
Подробнее про это есть тут: Batch Compilation, Recompilation, and Plan Caching Issues in SQL Server 2005

Все описанное вы можете наблюдать сами, запустив профайлер.
+ Профайлер с моими коментами

Картинка с другого сайта.
5 сен 13, 17:03    [14801003]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
чч
А во втором случае оптимизатор ожидает 200 записей для табличной переменной и только одну по кластерному индексу таблицы t1.Почему?

SSMS так показывает, у вас же теперь t1 на внутренней стороне loop join-а, вы обратите внимание на Estimated Number Of Executions, там все ок, рассчитывает получить 200 раз по одной строке, выполнив поиск 200 раз. Plan Explorer, например, показывает уже перемноженные значения, это более интуитивно понятно, имхо.
5 сен 13, 17:25    [14801118]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
чч
Guest
SomewhereSomehow
Колонка, это отвлекающий маневр =)
Все дело в рекомпиляции.


Я вам советую в следующий раз где-нибудь на конференции задать такой вопрос с колонкой :)
Наверняка не все приглядятся и с первого раза ответят :)
5 сен 13, 18:01    [14801311]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
чч
Guest
чч
SomewhereSomehow
Колонка, это отвлекающий маневр =)
Все дело в рекомпиляции.


Я вам советую в следующий раз где-нибудь на конференции задать такой вопрос с колонкой :)
Наверняка не все приглядятся и с первого раза ответят :)


Когда доклад будете читать
5 сен 13, 18:01    [14801316]     Ответить | Цитировать Сообщить модератору
 Re: анализ производительности запроса  [new]
SomewhereSomehow
Member

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

Боюсь, для вопроса тут слишком много букв, слушателям трудно будет сходу вникнуть, да и время ограничено, только если как пример, но за идею спасибо =) К докладу надеюсь подготовить примеры пореалистичнее и поинтереснее.
5 сен 13, 18:29    [14801431]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить