Dynamic Query VS Static Query Performance

Я написал 2 хранимые процедуры, которые читают одни и те же данные в зависимости от их параметров, одна из которых использует статический запрос sp_Order_Read1а другой использует динамический sp_Order_Read2, Они читают данные Orders стол в Northwind образец базы данных; на SQL Server 2012,

sp_Order_Read1:

create proc sp_Order_Read1 @OrderID int, @page int, @pageLength int
as begin
    if @OrderID is null
    begin
        if @page is not null and @pageLength is not null
            select OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry
                from Orders o
                order by o.OrderID
                offset (@page - 1) * @pageLength rows
                fetch next @pageLength rows only
        else
            select OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry
                from Orders o
    end
    else
    begin
        if @page is not null and @pageLength is not null
            select OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry
                from Orders o
                where o.OrderID = @OrderID
                order by o.OrderID
                offset (@page - 1) * @pageLength rows
                fetch next @pageLength rows only
        else
            select OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry
                from Orders o
                where o.OrderID = @OrderID
    end
end

sp_Order_Read2:

create proc sp_Order_Read2 @OrderID int, @page int, @pageLength int
as begin
    declare @query nvarchar(max) = ''
    if @OrderID is not null
    begin
        declare @OrderIDExpression nvarchar(max)
        if IsNumeric(@OrderID) = 1
            set @OrderIDExpression = @OrderID
        else
            set @OrderIDExpression = '''' + @OrderID + ''''
        set @query += 'declare @OrderID int = ' + @OrderIDExpression + ';
        '
    end
    if @page is not null and @pageLength is not null
    begin
        set @query += 'declare @page int = ' + convert(nvarchar(max), @page) + ';
        declare @pageLength int = ' + convert(nvarchar(max), @pageLength) + ';
        '
    end
    set @query +=
        'select OrderID, CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry
            from Orders o'
    if @OrderID is not null
        set @query += '
        where'
    if @OrderID is not null
        set @query += '
        OrderID = @OrderID'
    if @page is not null and @pageLength is not null
        set @query += '
        order by o.OrderID
        offset (@page - 1) * @pageLength rows
        fetch next @pageLength rows only'
    exec(@query)
end

* Обратите внимание, что я написал инструмент, который генерирует статический / динамический синтаксис для меня, поэтому написание либо не будет большой проблемой.

Я не мог решить, какой синтаксис будет работать быстрее, поэтому я решил проверить их. Я создал временную таблицу #comparison держать результаты.

create table #comparison
(
    ID int identity,
    One int,
    Two int
)

И тест был этот скрипт:

declare @counter int = 1
declare @count int = 50
declare @beginning1 datetimeoffset
declare @end1 datetimeoffset 
declare @beginning2 datetimeoffset
declare @end2 datetimeoffset
while(@counter <= @count)
begin
    set @beginning1 = sysdatetimeoffset()
        exec sp_Order_Read1 null, 5, 50
    set @end1 = sysdatetimeoffset()
    set @beginning2 = sysdatetimeoffset()
        exec sp_Order_Read2 null, 5, 50
    set @end2 = sysdatetimeoffset()
    insert #comparison (One, Two) values (datediff(microsecond, @beginning1, @end1), datediff(microsecond, @beginning2, @end2))
set @counter += 1
end

Я запускал его 5 раз, после каждого просмотра результатов с этим запросом:

select count(ID) as [Row Count], (sum(One) - sum(Two)) as [Difference] from #comparison

Затем я изменил порядок в тестовом скрипте так:

declare @counter int = 1
declare @count int = 50
declare @beginning1 datetimeoffset
declare @end1 datetimeoffset 
declare @beginning2 datetimeoffset
declare @end2 datetimeoffset
while(@counter <= @count)
begin
    set @beginning2 = sysdatetimeoffset()
        exec sp_Order_Read2 null, 5, 50
    set @end2 = sysdatetimeoffset()
    set @beginning1 = sysdatetimeoffset()
        exec sp_Order_Read1 null, 5, 50
    set @end1 = sysdatetimeoffset()
    insert #comparison (One, Two) values (datediff(microsecond, @beginning1, @end1), datediff(microsecond, @beginning2, @end2))
set @counter += 1
end

Я также запустил его 5 раз, и после каждого я смотрел результаты, используя тот же запрос. Результаты теста были следующими:

Row Count   Difference
---------------------------
100     439119
200     35963
300     2211699
400     14443
500     -2666605
--Reversed Excution Order--
600     5846095
700     13221704
800     21094312
900     28361390
1000    37526611

Результаты были довольно странными и неудовлетворительными для меня; поэтому, если бы кто-нибудь мог помочь мне решить, какой синтаксис должен работать быстрее, давая удовлетворительные аргументы, я был бы благодарен.

0 ответов

Другие вопросы по тегам