您好 我正在使用一个SP,它在服务器中需要7分钟,有7336个recrds 和另一台有3500条记录的服务器中的6秒。
有人能帮助我知道为什么会这样吗?
谢谢, -Divya
THE SP:
SELECT WORKSHEET_ID 来自PERSON PER INNER JOIN PERSON EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID 和 dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID,@ p_SEC_ACCOUNT_ID)> 0
LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN
ON PERSON_ASGN.ASSIGNMENT_ID =
dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
LEFT JOIN LOOKUP EMPLEE_ASGN_STAT
ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE'
AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
INNER JOIN
(SELECT w1.ASSIGNMENT_ID, w1.WORKSHEET_ID, w1.EFFECTIVE_DATE, w1.APPROVED_BY, w3.CREATED_BY
FROM WORKSHEET_PAYROLL_VW w1
INNER JOIN WORKSHEET w3
ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
WHERE w1.EFFECTIVE_DATE = CASE
WHEN @p_MOST_RECENT_ONLY = 'Y'
THEN (SELECT MAX(w2.EFFECTIVE_DATE)
FROM WORKSHEET_PAYROLL_VW w2
WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID
AND (ISNULL(@p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) =w2.EFFECTIVE_DATE))
ELSE ISNULL(@p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
END
)
PERSON_WKS
ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
INNER JOIN
(SELECT ASSIGNMENT_ID, VALUE
FROM ASSIGNMENT_HISTORY AH
WHERE FIELD_NAME ='HOME PAYROLL GROUP'
AND EFFECTIVE_DATE = (SELECT MAX(EFFECTIVE_DATE)
FROM ASSIGNMENT_HISTORY
WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID
AND EFFECTIVE_DATE <=getDate()
AND FIELD_NAME = 'HOME PAYROLL GROUP')
)HOME_PAYROLL
ON HOME_PAYROLL.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
WHERE
(@p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = @p_PERSON_ID)
AND
(@p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,1,1)
OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,2,1))
AND
(@p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = @p_POLICY_ID)
AND
(@p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=@p_HOME_COUNTRY_ID)
AND
(@p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=@p_HOME_CITY_ID )
AND
(@p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=@p_HOME_COMPANY_ID )
AND
(@p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=@p_HOME_DIVISION_ID )
AND
(@p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=@p_HOST_COUNTRY_ID )
AND
(@p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=@p_HOST_CITY_ID )
AND
(@p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=@p_HOST_COMPANY_ID )
AND
(@p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=@p_HOST_DIVISION_ID )
AND
(@p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=@p_CREATED_BY )
AND
(@p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=@p_APPROVED_BY )
AND
(@p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=@p_payroll_code )
按PER.LAST_NAME ASC订购, PER.FIRST_NAME ASC, PERSON_WKS.EFFECTIVE_DATE DESC
第5行中的函数是运行缓慢的函数。该部分的其余部分正在运行4secs
功能: 开始 宣布 @v_ASGN_COUNT INT, @v_RESULT INT
SELECT @v_ASGN_COUNT = COUNT(ASSIGNMENT_ID) --to find out if this employee has any assignment
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = @p_PERSON_ID AND
ASGN_STAT_CODE IN ('PD','A','I')
IF(@v_ASGN_COUNT > 0) --yes assignment, check against SECURITY_ASSIGNMENT_VW
BEGIN
SELECT @v_RESULT = COUNT(ASSIGNMENT_ID)
FROM SECURITY_ASSIGNMENT_VW
WHERE SEC_ACCOUNT_ID = @p_SEC_ACCOUNT_ID AND
ASSIGNMENT_ID IN (SELECT ASSIGNMENT_ID
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = @p_PERSON_ID AND
ASGN_STAT_CODE IN ('PD','A','I'))
END
ELSE --no assignment, so check against SECURITY_PERSON_VW
BEGIN
SELECT @v_RESULT = COUNT(PERSON_ID)
FROM SECURITY_PERSON_VW
WHERE SEC_ACCOUNT_ID = @p_SEC_ACCOUNT_ID AND
PERSON_ID = @p_PERSON_ID
END
RETURN @v_RESULT
END
答案 0 :(得分:1)
模式是否完全匹配...特别检查是否缺少索引。
答案 1 :(得分:1)
首先,你的标量函数会随着记录数量的增加而显着变慢,因为它们会逐行处理。不仅如果你需要性能,你已经在连接中使用了这些功能,这是一种可怕的做法。你有一堆OR条件往往会变慢。虽然实际阅读你发布的代码太难了(请尝试格式化并且只使用关键字的所有大写字母),但我怀疑其中一些条件并不是可以理解的。
要了解实际发生的情况,请查看执行计划(SQL Server)或解释计划(我认为是mySQL和其他人)或数据库中的等效功能。可能你会发现表扫描,当记录数量增加时,这些扫描当然会变得非常慢。
您可能还有参数嗅探问题。请谷歌看看如何解决这个问题。
答案 2 :(得分:0)
一个改进是确保dbo.FN_GETRPTSSIGNMENTID
仅执行一次。
目前,它被执行了三次 您可以通过加入(一)重新发送呼叫的字段来替换其中两个呼叫。
像
这样的东西SELECT WORKSHEET_ID
FROM PERSON PER
INNER JOIN PERSON EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID AND dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, @p_SEC_ACCOUNT_ID) > 0
INNER JOIN (
SELECT w1.ASSIGNMENT_ID
, w1.WORKSHEET_ID
, w1.EFFECTIVE_DATE
, w1.APPROVED_BY
, w3.CREATED_BY
FROM WORKSHEET_PAYROLL_VW w1
INNER JOIN WORKSHEET w3 ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
WHERE w1.EFFECTIVE_DATE =
CASE WHEN @p_MOST_RECENT_ONLY = 'Y'
THEN (
SELECT MAX(w2.EFFECTIVE_DATE)
FROM WORKSHEET_PAYROLL_VW w2
WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID AND (ISNULL(@p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) = w2.EFFECTIVE_DATE)
)
ELSE ISNULL(@p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
END
) PERSON_WKS ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
INNER JOIN (
SELECT ASSIGNMENT_ID
, VALUE
FROM ASSIGNMENT_HISTORY AH
WHERE FIELD_NAME ='HOME PAYROLL GROUP'
AND EFFECTIVE_DATE = (
SELECT MAX(EFFECTIVE_DATE)
FROM ASSIGNMENT_HISTORY
WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID
AND EFFECTIVE_DATE <=getDate()
AND FIELD_NAME = 'HOME PAYROLL GROUP'
)
LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN ON PERSON_ASGN.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
LEFT JOIN LOOKUP EMPLEE_ASGN_STAT ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE' AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
) HOME_PAYROLL ON HOME_PAYROLL.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
WHERE (@p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = @p_PERSON_ID)
AND (@p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,1,1) OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,2,1))
AND (@p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = @p_POLICY_ID)
AND (@p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=@p_HOME_COUNTRY_ID)
AND (@p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=@p_HOME_CITY_ID )
AND (@p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=@p_HOME_COMPANY_ID )
AND (@p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=@p_HOME_DIVISION_ID )
AND (@p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=@p_HOST_COUNTRY_ID )
AND (@p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=@p_HOST_CITY_ID )
AND (@p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=@p_HOST_COMPANY_ID )
AND (@p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=@p_HOST_DIVISION_ID )
AND (@p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=@p_CREATED_BY )
AND (@p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=@p_APPROVED_BY )
AND (@p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=@p_payroll_code )
ORDER BY
PER.LAST_NAME ASC
, PER.FIRST_NAME ASC
, PERSON_WKS.EFFECTIVE_DATE DESC