2015-10-22 170 views
2

我加入3个不同的表以实现自动完成功能,并且必须快速。建议必须回复良好且及时。我需要通过LIKE运算符来查看3个不同的字段以获得答案。见下面的细节。SQL Server 2008 R2存储过程很慢

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 + '%' 

上面的代码是缓慢(〜9sec)

  • 如果我使用:WHERE CMPNAME LIKE '%' + @Query + '%' =快;
  • 如果我使用:WHERE ADTOWN LIKE '%' + @Query + '%' = quick;
  • 如果我使用:WHERE CMPTHEIRCODE LIKE '%' + @Query + '%' = quick;

只是当我连接它们变慢时?

+2

你没有'sargable'谓词。你也在使用函数调用。这就是为什么它可能会很慢。如果可能的话,你也可以考虑把'union'改为'union all'。 –

+0

而不是连接,你可以'或'他们在一起吗?例如:'CMPNAME LIKE'%'+ @Query +'%'或ADTOWN LIKE'%'+ @Query +'%'或CMPTHEIRCODE LIKE'%'+ @Query +'%'' – DavidG

+0

我尝试了{OR}但它仍然很慢。它也不会真正适合要求,因为它们可以通过公司名称和城镇进行搜索,然后不会返回任何内容。 UNION ALL没有帮助。函数调用很好。请说明SARGABLE谓词建议? – cocojiambo

回答

0

我会尝试是这样的:

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 

我试图重新实现你的3个条件的逻辑上,你有索引的列上的参数运行,而不是。我的假设是,在这种情况下,索引将被使用。

PS:当发现/减少charindex的结果时,需要进行小的调整migth,以防我在计算中犯了一些错误,但希望你明白了。 - SQLFiddle to validate that the CHARINDEX() comparisons are correct

另外,我建议/尝试查询的顶部做一些修改,以便在年底你的脚本应该是这样的:

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 

希望它能帮助。

+0

谢谢拉杜。只要我一秒钟就会尝试你的建议。会让你知道。 – cocojiambo

+0

@cocojiambo你有没有机会检查这个运行速度是否更快? –

+0

它确实回来了[非常快,但无论我输入什么,它都不会返回结果。尝试调试它并查看可能的错误。如果我成功了,会让你知道。感谢您的跟进。 – cocojiambo

相关问题