Ускорьте эту хранимую процедуру Sybase - PullRequest
0 голосов
/ 15 июля 2011

У меня есть эта хранимая процедура, которую я использую для заполнения пользовательской таблицы.Это кажется медленным, потому что это занимает в среднем.6с, чтобы вернуть записи.Есть ли что-нибудь еще, что я могу сделать, чтобы настроить этот sproc, чтобы он стал быстрее?

CREATE PROCEDURE dbo.usmGetPendingAuthorizations
(
    @empCorpId char(8) = null,
    @empFirstName char(30) = null,
    @empLastName char(30) = null,
    @accessCompletionStatus char(20) = null,
    @ownerCorpId char(8) = null,
    @reqCorpId char(8) = null,
    @reqDate datetime = null,
    @rowCount int = 100
)
AS BEGIN       

    SET ROWCOUNT @rowCount

    SELECT
        UPPER(LTRIM(RTRIM(pa.RequestorCorpId))) AS ReqCorpId, 
        UPPER(LTRIM(RTRIM(pa.AccessCompletionStatus))) AS AccessCompletionStatus, 
        UPPER(LTRIM(RTRIM(pa.Comment))) AS ReqComment, 
        UPPER(LTRIM(RTRIM(pa.ValidLoginInd))) AS ValidLoginInd, 
        UPPER(LTRIM(RTRIM(pa.OwnerCorpId))) AS OwnerCorpId, 
        UPPER(LTRIM(RTRIM(pa.UserTypeCode))) AS UserTypeCode, 
        UPPER(LTRIM(RTRIM(pa.SelectMethod))) AS SelectMethod, 
        pa.ExpirationDate AS ExpirationDate, 
        pa.RequestorDate AS ReqDate, 
        pa.BeginDate AS BeginDate, 
        pa.EndDate AS EndDate, 
        UPPER(LTRIM(RTRIM(pa.UserGroupTypeCode))) AS UserGroupTypeCode,
        pa.SubsidiaryId AS SubsidiaryId,    
        UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) AS EmpCorpId,
        emp.empKeyId AS EmpKeyId,
        LTRIM(RTRIM(emp.firstName)) AS EmpFirstName,
        LTRIM(RTRIM(emp.lastName)) AS EmpLastName
    FROM
        dbo.PendingAuthorization AS pa JOIN capmark..EmployeeDataExtract AS emp
    ON
        UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) = UPPER(LTRIM(RTRIM(emp.corporateId)))
    WHERE
        UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) LIKE ISNULL(UPPER(LTRIM(RTRIM(@empCorpId))), '%')
        AND UPPER(LTRIM(RTRIM(emp.firstName))) LIKE ISNULL('%' + UPPER(LTRIM(RTRIM(@empFirstName))) + '%', '%')
        AND UPPER(LTRIM(RTRIM(emp.lastName))) LIKE ISNULL('%' + UPPER(LTRIM(RTRIM(@empLastName))) + '%', '%')
        AND pa.AccessCompletionStatus LIKE ISNULL(UPPER(LTRIM(RTRIM(@accessCompletionStatus))), '%')
        AND pa.OwnerCorpId LIKE ISNULL(UPPER(LTRIM(RTRIM(@ownerCorpId))), '%')
        AND pa.RequestorCorpId LIKE ISNULL(UPPER(LTRIM(RTRIM(@reqCorpId))), '%')
        AND DATEDIFF(dd, pa.RequestorDate, CONVERT(VARCHAR(10), ISNULL(@reqDate, pa.RequestorDate), 101)) = 0

    SET ROWCOUNT 0
END

Ответы [ 2 ]

1 голос
/ 16 июля 2011

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

ON
    UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) = UPPER(LTRIM(RTRIM(emp.corporateId)))

Действительно ли нужны все эти планки и верх?

Если у вас хранятся грязные данные - смешанный регистр, с небольшим начальным и последним пробелом, я советую вам попытаться ужесточить способ хранения и / или обновления данных - не позволяйте таким данным входить. Выполните однократную очистку данных, чтобы все корпоративные идентификаторы были прописными без пробелов или пробелов.

Получив чистые данные, вы можете добавить индекс по столбцу corporateId в таблице EmployeeDataExtract (или перестроить его, если он уже существует) и изменить соединение на

ON
    pa.EmployeeCorpId = emp.corporateId

Если вы действительно не можете обеспечить чистоту данных в таблице PendingAuthorization, вам придется оставить перенос функций на этой стороне объединения, но по крайней мере индекс в таблице emp будет доступен для оптимизатора. рассмотреть.

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

Похоже, что поле PendingAuthorization.RequestorDate используется для выбора данных только для одной даты - той, которая указана в @reqDate. Вы можете преобразовать эту часть предложения WHERE в запрос диапазона, тогда можно использовать индекс в поле даты. Чтобы сделать это, вы должны использовать только часть даты @reqDate (игнорируя время суток), а затем извлекать ее из этой «даты + 1». Это будут используемые значения. Много ли это поможет, зависит от того, сколько дней RequestorDate присутствует в таблице PendingAuthorization.

0 голосов
/ 15 июля 2011

Хотя вы, кажется, никогда не принимали никакого ответа, я постараюсь вам помочь:).

Во-первых, я бы пересмотрел предложение WHERE. Вместо твоего НРАВИТСЯ:

UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) LIKE ISNULL(UPPER(LTRIM(RTRIM(@empCorpId))), '%')

Я бы использовал это:

(UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) LIKE UPPER(LTRIM(RTRIM(@empCorpId)))) OR (@empCorpId IS NULL)

Итак, можете ли вы попробовать следующее предложение WHERE вместо своего, чтобы увидеть, есть ли разница в производительности?

WHERE
    (UPPER(LTRIM(RTRIM(pa.EmployeeCorpId))) LIKE UPPER(LTRIM(RTRIM(@empCorpId))) OR @empCorpId IS NULL)
    AND (UPPER(LTRIM(RTRIM(emp.firstName))) LIKE '%' + UPPER(LTRIM(RTRIM(@empFirstName))) + '%' OR @empFirstName IS NULL)
    AND (UPPER(LTRIM(RTRIM(emp.lastName))) LIKE '%' + UPPER(LTRIM(RTRIM(@empLastName))) + '%' OR @empLastName IS NULL)
    AND (pa.AccessCompletionStatus LIKE UPPER(LTRIM(RTRIM(@accessCompletionStatus))) OR @accessCompletionStatus IS NULL)
    AND (pa.OwnerCorpId LIKE UPPER(LTRIM(RTRIM(@ownerCorpId))) OR @ownerCorpId IS NULL)
    AND (pa.RequestorCorpId LIKE UPPER(LTRIM(RTRIM(@reqCorpId))) OR @reqCorpId IS NULL)
    AND (DATEDIFF(dd, pa.RequestorDate, CONVERT(VARCHAR(10), ISNULL(@reqDate, pa.RequestorDate), 101)) = 0)

Во-вторых, как правило, SELECT работает быстрее, если столбцы, на которые есть ссылки в предложении WHERE, проиндексированы надлежащим образом.

Тогда DATEDIFF и предложение CONVERT в предложении WHERE также не ускорят ваш запрос.

Но главный вопрос: сколько строк в соединенных таблицах? Потому что 6 секунд может быть не так уж плохо. Вы можете проверить / поиграть с планом Query, чтобы выяснить потенциальные узкие места.

...