简体   繁体   English

SQL Server 2008 R2存储过程很慢

[英]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)

  • If I use: WHERE CMPNAME LIKE '%' + @Query + '%' = quick; 如果使用: WHERE CMPNAME LIKE '%' + @Query + '%' = quick;
  • If I use: WHERE ADTOWN LIKE '%' + @Query + '%' = quick; 如果我使用: WHERE ADTOWN LIKE '%' + @Query + '%' = quick;
  • If I use: 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM