Если в вашем коде TSQL много вложенных вызовов stored procedures, вы можете наглядно построить стек вызовов с помощью «flame chart» — стандартным представлением для профилирования вызовов.

Опишем по шагам всю процедуру.
Создание трейса
Запустите SQL profiler и выберете события:
-
SP:Starting
-
SP:Completed
Выберите следующие колонки:
-
ObjectName
-
NestLevel
-
StartTime
-
EndTime
-
Spid
В фильтрах укажите условие по Spid на равенство — это важно. Анализируется только один поток выполнения. Записав достаточно событий, сохраните трейс в базу данных. В базе данных создайте следующую процедуру:
Скрытый текст
create procedure flame @trname sysname, @spname sysname, @start int=0 as -- Trace must contain Sp:Start, Sp:Completed, StartTime, EndTime, Nestlevel, ObjectName -- 1 SPID should be recorded set nocount on declare @r int, @b int, @e int, @t datetime, @class int, @lev int, @obj varchar(255), @prevt datetime, @stack varchar(max)='', @prevstack varchar(max)='', @sql varchar(1000) create table #trace (RowNumber int, EventClass int, StartTime datetime, EndTime datetime, NestLevel int, ObjectName nvarchar(255)) set @sql = 'insert into #trace select RowNumber,EventClass,StartTime,EndTime,Nestlevel,ObjectName from '+@trname+' where EventClass in (42,43)' exec (@sql) select (select max(RowNumber) from #trace I where I.EventClass=42 and I.ObjectName=@spname and I.Nestlevel=1 and I.RowNumber<O.RowNumber) as [Start], O.RowNumber as [End], StartTime, EndTime, datediff(ms, StartTime, endTime) as DurationMs from #trace O where EventClass=43 and ObjectName=@spname and Nestlevel=1 order by 1 select @b=min(RowNumber) from #trace where EventClass=42 and ObjectName=@spname and NestLevel=1 and RowNumber>=@start if @b is null begin print 'procedure: start not found' return end select @e=min(RowNumber) from #trace where EventClass=43 and ObjectName=@spname and RowNumber>@b and Nestlevel=1 if @e is null begin print 'procedure: end not found' return end select 'Selected', @b as [Start], @e as [End] DECLARE my_cur CURSOR FOR SELECT RowNumber,EventClass,isnull(EndTime,StartTime),NestLevel,ObjectName from #trace where RowNumber>=@b and RowNumber<=@e order by RowNumber OPEN my_cur FETCH NEXT FROM my_cur INTO @r, @class, @t, @lev, @obj WHILE @@FETCH_STATUS = 0 BEGIN if @class=42 set @stack = @stack + ';' + @obj else set @stack=reverse(substring(reverse(@stack),charindex(';', reverse(@stack))+1,100000)) if @prevt is not null print substring(@prevstack,2,100000)+' '+convert(varchar,datediff(ms,@prevt,@t)) set @prevt=@t set @prevstack=@stack FETCH NEXT FROM my_cur INTO @r, @class, @t, @lev, @obj END CLOSE my_cur DEALLOCATE my_cur GO
Генерация данных
Запустите процедуру flame указав параметры:
-
имя таблицы с трейсом
-
имя процедуры для построения диаграммы. Процедура должны быть на самом верхнем уровне вызова (NestLevel=1). Имя указывается без скобок и схемы, то есть вместо [dbo].[myProc] указываем myProc
-
третий параметр опционален, по умолчанию 0. Позволяет выбрать конкретное выполнение, если их много
Пример:

Первая табличка показывает все найденные выполнения данной функции, диапазон RowNumber, диапазон времен и длительность в миллисекундах
Если нас интересует не самое первое выполнение, то указываем в третьем параметре Start нужного нам. Во втором результате указывается выполнение, выбранное к анализу. Например, для 9го исполнения указываем значение 10574
Построение диаграммы
Убедившись, что все в порядке, заглянем во вкладку Messages и скопируем результат в текстовый файл, удалив в самом конце ненужное вместе с пустой строкой:

Далее идем на сайт https://www.speedscope.app и загружаем созданный нами файл. Готово.

ссылка на оригинал статьи https://habr.com/ru/articles/892876/
Добавить комментарий