加速此Sybase存储过程

时间:2011-07-15 15:59:48

标签: sql query-optimization sybase

我有这个存储过程,我用它来填充用户表。这似乎很慢,因为它正在平均值。 6s返回记录。还有什么我可以做的来调整这个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 个答案:

答案 0 :(得分:1)

主要问题是功能的自由使用,特别是在连接中。在以这种方式使用函数的地方,Sybase无法利用这些字段上的索引。以加入

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

是否真的需要所有修剪和鞋面?

如果您存储了脏数据 - 混合大小写,有一些前导空格和一些尾随空格,我建议您尝试收紧数据的存储和/或更新方式 - 不要让这些数据进入。执行一次性数据清理,使所有公司ID大写,没有尾随或前导空格。

获得干净数据后,您可以在EmployeeDataExtract表中的corporateId列上添加索引(如果已存在,则重建它)并将连接更改为

ON
    pa.EmployeeCorpId = emp.corporateId

如果您确实无法确保PendingAuthorization表中的干净数据,那么您必须将函数保留在连接的那一侧,但至少emp表上的索引可用于要考虑的优化者。

使用带有前沿通配符的LIKE会使索引无法使用,但在您的情况下这可能是不可避免的。

看起来PendingAuthorization.RequestorDate字段仅用于为一个日期选择数据 - @reqDate中提供的日期。您可以将WHERE子句的该部分转换为范围查询,然后可以使用日期字段上的索引。 要做到这一点,你只需使用@reqDate的日期部分(忽略时间),然后从'date + 1'派生。这些将是使用的值。这是否有用将取决于PendingAuthorization表中存在多少RequestorDate天。

答案 1 :(得分:0)

虽然您似乎从未接受任何答案,但我会尽力帮助您:)。

首先,我会修改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)

其次,一般情况下,如果WHERE子句中引用的列被正确索引,则SELECT的工作速度会更快。

然后,DATEDIFF和WHERE子句中的CONVERT也不会加速你的查询。

但是,主要问题是:连接表中有多少行?因为6秒可能不那么糟糕。您可以查看/玩查询计划,找出任何潜在的瓶颈。