2011-07-15 47 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