SQL Нефиксируемый параметр сниффинг?Занимает секунды в SSMS, минуты в SSRS - PullRequest
1 голос
/ 14 марта 2019

У меня есть отчет.Запросы выполняются в течение нескольких секунд в Microsoft SSMS (SQL Server Management Studio), но всякий раз, когда я запускаю отчет через SSRS в Visual Studio, теперь отчет занимает минуты.Я много об этом читал, и все говорят, что это анализ параметров, но я попробовал все решения для анализа параметров, и они, похоже, ничего не делают.

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

Вот мой запрос, он немного длинный и сложный, но здесь проблема не в этом.И да, я знаю, что это не правильный способ использования nolock, но именно так мой работодатель попросил меня использовать nolock.

SELECT DISTINCT 

DENSE_RANK() OVER (PARTITION BY O.Customer_Number ORDER BY O.Customer_Purchase_Order_Number ASC) 
    + DENSE_RANK() OVER (PARTITION BY O.Customer_Number ORDER BY O.Customer_Purchase_Order_Number DESC) 
         - 1 AS Total_Orders_Count

,COUNT(*) OVER () AS Total_Units_Count

 ,Sum(S.Retail  * OD.Quantity_Ordered) OVER (PARTITION BY O.Customer_Number) as Total_Net_Value

,Sum(OD.Price * OD.Quantity_Ordered) OVER (PARTITION BY O.Customer_Number) as Price
,Sum(OD.Discount_Value) OVER (PARTITION BY O.Customer_Number) as Discount_Value
,Sum(OD.Freight_Charges) OVER (PARTITION BY O.Customer_Number) as Freight_Charges
,Sum(OD.Tax_Value) OVER (PARTITION BY O.Customer_Number) as Tax_Value


,SUM(CASE WHEN O.Order_Status = '30' then 1 ELSE 0 END) OVER (PARTITION BY O.Customer_Number) as "Cancelled_Orders"
,SUM(CASE WHEN OD.Line_Status = '80' then 1 ELSE 0 END) OVER (PARTITION BY O.Customer_Number) as "Cancelled_Lines"
,Sum (T.Cost) OVER () Total_Product_Cost
,Avg (T.Cost) OVER () Avg_Product_Cost

FROM 
    [JMNYC-AMTDB].[AMTPLUS].[dbo].Orders O (nolock)

LEFT JOIN 
    [JMNYC-AMTDB].[AMTPLUS].[dbo].Order_Detail OD (nolock) On O.Company_Code =
        OD.Company_Code And O.Division_Code =
        OD.Division_Code And O.Control_Number =
        OD.Control_Number

LEFT JOIN
    [JMNYC-AMTDB].[AMTPLUS].[dbo].[Z_N_RetailPrices] S (nolock) On 
        OD.Item_Number = S.SKU

LEFT JOIN
    (
    Select
    T.Sku,
    CASE WHEN T.AvgCostActual is NULL THEN T.AvgCostStandard ELSE T.AvgCostActual END Cost

    From(
        Select distinct 

        Z.Sku, 
        AVG (CASE WHEN st.Actual_Cost <> 0 THEN st.Actual_Cost ELSE NULL END) OVER (PARTITION BY Z.Sku) AvgCostActual,
        AVG (CASE WHEN st.Standard_Cost <> 0 THEN st.Standard_Cost ELSE NULL END) OVER (PARTITION BY Z.Sku) AvgCostStandard
        From 

            [JMNYC-AMTDB].[AMTPLUS].[dbo].[Z_N_RetailPrices] Z

        LEFT JOIN

            [JMNYC-AMTDB].[AMTPLUS].[dbo].Style St (nolock) On 
            Z.Sku = St.Item_Number
        ) T  
    ) T on OD.Item_Number = T.Sku

WHERE 
    (O.Company_Code = @CompanyCode OR @CompanyCode IS NULL) AND 
    (O.Division_Code = @DivisionCode OR @DivisionCode IS NULL) AND
    o.Customer_Number = 'ecom2x' AND 
    ISNUMERIC(O.Customer_Purchase_Order_Number) <> 0 AND
    o.DateRecordModified BETWEEN @FromDate AND DATEADD(dayofyear, 1, @ToDate)

Я могу добавить это перед запросом в MSSMS (поскольку мне нужно объявить параметры, если я не выбираю их через SSRS), и запрос выполняется в считанные секунды.

DECLARE @CompanyCode VARCHAR(5)
SET @CompanyCode = '03'

DECLARE @DivisionCode VARCHAR(5)
SET @DivisionCode = '001'

DECLARE @FromDate DATETIME
SET @FromDate = '2/1/2019'

DECLARE @ToDate DATETIME
SET @ToDate = '3/1/2019'

В SSRS это занимает минуты с теми же параметрами.

Я попытался добавить следующий код в мой SSRS-запрос, чтобы ускорить его (все говорят, что это решение для перехвата параметров)

Declare @LocalCompanyCode NVARCHAR(5) = @CompanyCode
Declare @LocalDivisionCode NVARCHAR(5)= @DivisionCode
Declare @LocalToDate DATETIME= @ToDate
Declare @LocalFromDate DATETIME= @FromDate

И затем изменил предложение Where, чтобы использовать этилокальные переменные

WHERE 
    (O.Company_Code = @LocalCompanyCode OR @LocalCompanyCode IS NULL) AND 
    (O.Division_Code = @LocalDivisionCode OR @LocalDivisionCode IS NULL) AND
    o.Customer_Number = 'ecom2x' AND 
    ISNUMERIC(O.Customer_Purchase_Order_Number) <> 0 AND
    o.DateRecordModified BETWEEN @LocalFromDate AND DATEADD(dayofyear, 1,@LocalToDate)

Но это ничего не меняет, и запрос по-прежнему занимает минуты в SSRS и секунды в SSMS.

Я тоже пытался использовать Recompile, тоже самое.

Кто-нибудь знает, что я могу сделать?

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

Вы пробовали подсказку запроса OPTIMIZE FOR? Например. OPTION (OPTIMIZE FOR (@LocalCompanyCode = 5, @LocalDivisionCode = 1)) --Choose representative examples of what values are normally used for the variables, это идет после предложения where, и вы можете указать столько пар параметров-значений, сколько необходимо, разделяя их запятой. Вы также можете использовать ключевое слово UNKNOWN, когда не знаете лучшего значения, но иногда это приводит к неоптимальным планам

0 голосов
/ 14 марта 2019

Кто-нибудь знает, что я могу сделать?

  • SET OPTIONS в SSRS отличаются от SET options в SSMS. Подумайте о том, чтобы сделать их равными, сравнив и включив один и тот же набор в обоих приложениях, поскольку их несоответствие может быть реальной причиной разницы в производительности

  • Если первый элемент не принес никаких улучшений и действительно обнаружен параметр, попробуйте добавить OPTION (RECOMPILE) в конце запроса.

Параметры SET можно проверить с помощью:

DBCC USEROPTIONS

Набор параметров «SET» по умолчанию в SSMS:

SET quoted_identifier ON;   
SET arithabort ON;
SET SET ansi_null_dflt_on;  
SET ansi_warnings ON;   
SET ansi_padding ON;    
SET ansi_nulls ON;  
SET concat_null_yields_null ON;

Чтобы проверить влияние на запрос, их можно добавить до SELECT

...