[英]SQL Server 2008 R2 stored procedure is slow
I am joining 3 different tables for an auto-complete functionality and it has to be quick. 我要加入3个不同的表以实现自动完成功能,并且必须快速。 The suggestions have to come back nice and prompt. 建议必须很好,迅速地返回。 I need to look through 3 different fields for the answer with a LIKE
operator. 我需要通过3个不同的字段来查找LIKE
运算符的答案。 See details below. 请参阅下面的详细信息。
DECLARE @Space AS CHAR(1) = ' ';
SELECT TOP (@QuantityToReturn) *
FROM
(SELECT
C.CMPID, C.CMPNAME, C.CMPTHEIRCODE, AD.ADTOWN
FROM COMPANY C
JOIN [dbo].[COMPADDRESS] CA ON CA.CMPID = C.CMPID
JOIN [dbo].[ADDRESS] ad ON AD.ADID = CA.ADID
JOIN [dbo].SUPPLIER SUP ON C.CMPID = SUP.CMPID
WHERE
(C.CMPID = @LoggedInUserId
OR @LoggedInUserId = dbo.fnIsAParentCompanyOf(@LoggedInUserId, C.CMPID)
OR @LoggedInUserId = 12345)
UNION
SELECT
C.CMPID, C.CMPNAME, C.CMP_THEIRCODE, AD.ADTOWN
FROM COMPANY C
JOIN [dbo].[COMPADDRESS] CA ON ca.CMPID = C.CMPID
JOIN [dbo].[ADDRESS] AD ON AD.ADID = CA.ADID
JOIN [dbo].CUSTOMER CUS ON C.CMPID = CUS.CMPID AND CUS.CUSTISTHIS = 1
WHERE
(C.CMPID = @LoggedInUserId
OR @LoggedInUserId = dbo.fnIsAParentCompanyOf(@LoggedInUserId, C.CMPID)
OR @LoggedInUserId = 12345)
) AS Results
WHERE
(CMPNAME + @Space + ADTOWN + @Space + CMPTHEIRCODE) LIKE '%' + @Query + '%'
The above code is slow (~ 9sec) 上面的代码很慢(〜9sec)
WHERE CMPNAME LIKE '%' + @Query + '%'
= quick; 如果使用: WHERE CMPNAME LIKE '%' + @Query + '%'
= quick; WHERE ADTOWN LIKE '%' + @Query + '%'
= quick; 如果我使用: WHERE ADTOWN LIKE '%' + @Query + '%'
= quick; WHERE CMPTHEIRCODE LIKE '%' + @Query + '%'
= quick; 如果我使用: WHERE CMPTHEIRCODE LIKE '%' + @Query + '%'
= quick; It is just when I concatenate them that goes slow? 只是当我连接它们时,速度变慢了吗?
What I would try is this: 我会尝试的是这样的:
WHERE
LEN(@Query) <> LEN(REPLACE(@Query, CMPNAME, ''))
AND (LEN(@Query) <> LEN(REPLACE(@Query, ADTOWN, ''))
AND CHARINDEX(CMPNAME, @Query) = (CHARINDEX(ADTOWN, @Query) - 1 - LEN(CMPNAME))
) -- making sure that the value of ADTOWN comes after CMPNAME
AND (LEN(@Query) <> LEN(REPLACE(@Query, CMPTHEIRCODE, ''))
AND CHARINDEX(ADTOWN, @Query) = (CHARINDEX(CMPTHEIRCODE, @Query) - 1 - LEN(ADTOWN))
) -- making sure that the value of CMPTHEIRCODE comes after ADTOWN
I've tried re-implementing the logic of your 3 conditions to run on the parameters and not on the columns on which you have indexes. 我尝试重新实现您的3个条件的逻辑,以便在参数上而不是在具有索引的列上运行。 My assumption is that in this scenario the indexes will be used. 我的假设是在这种情况下将使用索引。
PS: Small adjustments migth be needed when finding / substracting charindex's results, in case i made some mistakes in my calculations, but hopefully you got the idea. PS:查找/减去charindex的结果时,需要进行一些细微的调整,以防万一我在计算中犯了一些错误,但是希望您能理解。 - SQLFiddle to validate that the CHARINDEX() comparisons are correct . -SQLFiddle以验证CHARINDEX()比较是否正确 。
Also, I would recommend / try some additional changes to the top part of the query so in the end your script would look like this: 另外,我建议/尝试对查询的顶部进行一些其他更改,以便最终脚本如下所示:
DECLARE @Space AS CHAR(1) = ' ';
SELECT TOP (@QuantityToReturn) *
FROM (
SELECT C.CMPID
,C.CMPNAME
,C.CMPTHEIRCODE
,AD.ADTOWN
FROM COMPANY C
INNER JOIN [dbo].[COMPADDRESS] CA
ON CA.CMPID = C.CMPID
INNER JOIN [dbo].[ADDRESS] ad
ON AD.ADID = CA.ADID
WHERE (
C.CMPID = @LoggedInUserId
OR @LoggedInUserId = dbo.fnIsAParentCompanyOf(@LoggedInUserId, C.CMPID)
OR @LoggedInUserId = 12345
)
AND EXISTS (
SELECT 1
FROM [dbo].SUPPLIER SUP
WHERE C.CMPID = SUP.CMPID
)
UNION
SELECT C.CMPID
,C.CMPNAME
,C.CMP_THEIRCODE
,AD.ADTOWN
FROM COMPANY C
INNER JOIN [dbo].[COMPADDRESS] CA
ON ca.CMPID = C.CMPID
INNER JOIN [dbo].[ADDRESS] AD
ON AD.ADID = CA.ADID
WHERE (
C.CMPID = @LoggedInUserId
OR @LoggedInUserId = dbo.fnIsAParentCompanyOf(@LoggedInUserId, C.CMPID)
OR @LoggedInUserId = 12345
)
AND EXISTS (
SELECT 1
FROM [dbo].CUSTOMER CUS
WHERE C.CMPID = CUS.CMPID
AND CUS.CUSTISTHIS = 1
)
) AS Results
WHERE LEN(@Query) <> LEN(REPLACE(@Query, CMPNAME, ''))
AND (
LEN(@Query) <> LEN(REPLACE(@Query, ADTOWN, ''))
AND CHARINDEX(CMPNAME, @Query) = (CHARINDEX(ADTOWN, @Query) - 1 - LEN(CMPNAME))
) -- making sure that the value of ADTOWN comes after CMPNAME
AND (
LEN(@Query) <> LEN(REPLACE(@Query, CMPTHEIRCODE, ''))
AND CHARINDEX(ADTOWN, @Query) = (CHARINDEX(CMPTHEIRCODE, @Query) - 1 - LEN(ADTOWN))
) -- making sure that the value of CMPTHEIRCODE comes after ADTOWN
Hope it helps. 希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.