2011-07-15 42 views
0

我有这个存储过程,我正在使用它来填充用户表。它似乎很慢,因为它花费了平均。 6s返回记录。还有什么我可以做的调整这个sproc使其更快?加快此Sybase存储过程

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

摆脱所有这些'LIKE'语句。 –

+1

有多少条记录正在返回?对于100万条记录,零记录的6s与6s的差异很大? –

+2

你说'其他' - 你可能会说出你迄今为止所尝试过的吗? –

回答

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的日期部分(忽略一天中的时间),然后从该日期+ 1中派生出来。这些将是使用的值。这是否有很大帮助取决于PendingAuthorization表中有多少个RequestorDate日期。

+0

事实证明,这是JOIN上正在使用的函数正在减慢sproc。 – VajNyiaj

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和CONVERT在WHERE子句中也不会加快您的查询速度。

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

+0

capmark..EmployeeDataExtract表中大约有大约500K +行。 – VajNyiaj

+0

然后我会查看查询计划。 –

+0

所有LIKE的原因是最终用户可以使用这些输入参数的任意组合来进行查询。加入的唯一原因是firstName和lastName存储在Employee表中,其中Pending Auth表只存储员工的ID。 – VajNyiaj