SQL-запрос работает медленно - сниффинг параметров - PullRequest
0 голосов
/ 25 января 2019

У меня есть простой запрос, где я возвращаю список заказов по диапазону дат.Этот запрос используется в отчете, который передает его параметры (Site, From Date и To Date).

ALTER PROCEDURE [dbo].[Z_N_ECOM_ORDER_STATUS_DATERANGE]
    @Site VARCHAR(5),
    @FromDate DATETIME,
    @ToDate DATETIME
AS
BEGIN
    SET NOCOUNT ON;

    SELECT
        o.Company_Code,
        o.Division_Code,
        o.Control_Number,
        RTRIM(o.Customer_Purchase_Order_Number) AS Shopify_Num,
        CASE 
           WHEN p.PickTicket_Number IS NULL
              THEN i.PickTicket_Number 
              ELSE p.PickTicket_Number 
        END PickTicket_Number,
        i.Invoice_Number,
        o.Date_Entered,
        CASE
           WHEN ph.packslip IS NULL AND i.invoice_number IS NULL  
                AND P.pickticket_number IS NULL
              THEN 'Cancelled' 
           WHEN ph.packslip IS NULL AND i.invoice_number IS NULL 
                AND DATEADD(minute, 90, o.date_entered) > CURRENT_TIMESTAMP
              THEN 'Not Entered Yet'  
           WHEN ph.packslip IS NULL 
              THEN 'SHIPPED & UPLOADED' 
           ELSE RTRIM (z.status) 
        END Accellos_Status, 
        b.UPS_Tracking_Number Tracking_Number
    FROM
        [JMNYC-AMTDB].[AMTPLUS].[dbo].Orders o (nolock)
    LEFT JOIN
        [JMNYC-AMTDB].[AMTPLUS].[dbo].PickTickets p (nolock) ON o.Company_Code = p.Company_Code 
                                                         AND o.Division_Code = p.Division_Code 
                                                         AND o.Control_Number = p.Control_Number
    LEFT JOIN
        [JMNYC-AMTDB].[AMTPLUS].[dbo].Invoices i (nolock) ON o.Company_Code = i.Company_Code 
                                                      AND o.Division_Code = i.Division_Code 
                                                      AND o.Control_Number = i.Control_Number   
    LEFT JOIN
        [JMNYC-AMTDB].[AMTPLUS].[dbo].box b (nolock) ON o.Company_Code = b.Company_Code 
                                                AND o.Division_Code = b.Division_Code 
                                                AND i.PickTicket_Number = b.PickTicket_Number
    LEFT JOIN
        pickhead ph (nolock) ON p.PickTicket_Number = ph.packslip
    LEFT JOIN
        Z_Status z (nolock) ON ph.PROCSTEP = z.procstep
    WHERE 
        o.Company_Code = LEFT(@Site, 2)
        AND o.Division_Code = RIGHT(@Site, 3) 
        AND o.Customer_Number = 'ecom2x'
        AND o.Date_Entered BETWEEN @FromDate AND DATEADD(dayofyear, 1, @ToDate)
    ORDER BY 
        o.date_entered DESC
END

Проблема этого запроса заключается в том, что он занимает слишком много времени, и проблемные строки имеют значение * 1004.*

 WHERE 
     o.Company_Code = LEFT(@Site, 2)
     AND o.Division_Code = RIGHT(@Site, 3)

Формат сайта переменной - что-то вроде '09001' или '03001', где левая сторона - это компания, а правая - это деление

Потому что, когда я запускаю этот запрос сжестко закодированные значения, он работает практически мгновенно.Когда я использую параметры, это занимает минуты.

Итак, я посмотрел его и обнаружил анализ параметров.Поэтому я добавил следующую строку после начала оператора.

DECLARE @LocalSite VARCHAR(5) = CAST(@Site AS VARCHAR(5))

Тем не менее, он все еще работает очень медленно.

Мой новый оператор where будет

WHERE 
    o.Customer_Number = 'ecom2x'
    AND o.Date_Entered BETWEEN @FromDate AND DATEADD(dayofyear, 1,  @ToDate)
    AND ((@LocalSite = '00000') OR (O.Company_Code = LEFT(@LocalSite, 2) AND O.Division_Code = RIGHT(@LocalSite, 3))) 
order by o.date_entered desc*

Я также хочу, чтобы у пользователя была возможность выбора всех сайтов, которые сделают переменную сайта '00000', и поэтому не должнызапустить проверку кода компании / подразделения.Этот текущий оператор where делает запрос очень медленным.

Кто-нибудь знает, что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Пробовали ли вы взять левое и правое значения параметра @ site в двух разных переменных и использовать эти переменные в SP.

Например,

Declare @compcode as varchar(2)
Declare @divcode as varchar(3)
Set @compcode=LEFT(@Site, 2)
Set @divcode=RIGHT(@Site, 3)

Ваше условие "где"

WHERE 
o.Company_Code = @compcode
AND o.Division_Code = @divcode
0 голосов
/ 25 января 2019

Можете ли вы попытаться избежать использования LEFT () и RIGHT (), объявив несколько переменных и присвоив значения этим переменным, а затем используя их в операторе SELECT?

подсказка, ОПТИМИЗИРОВАННАЯ ДЛЯ НЕИЗВЕСТНОГО, чтобы избежать перехвата параметров:

option (OPTIMIZE FOR (@p1 UNKNOWN, @p2 UNKNOWN))

Где p1 и p2 эти две переменные, упомянутые выше

Я также хочу, чтобы пользователь имел возможность выбора всех сайтов что сделает переменную сайта '00000' и, следовательно, она не должна запускаться проверка кода компании / подразделения. Это текущее, где заявление делает запрос выполняется очень медленно.

Это можно оптимизировать, заменив текущий оператор SELECT на оператор IF, который использует два SELECT. Если значение равно 00000, просто избегайте проверки компании и подразделения, в противном случае выполните тот же выбор, но с этими дополнительными проверками

Еще одна поразительная вещь - это запрос связанных серверных объектов с дальнейшим объединением в локальные таблицы. Попробуйте разделить это на отдельный шаг, например, путем сохранения данных во временной таблице (не в табличной переменной!) В качестве промежуточного результата. Затем временная таблица должна быть объединена с локальными объектами. Это может повысить точность плана запросов из-за более точных оценок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...