2015-10-22 4 views
2

Я присоединяюсь к 3 различным таблицам для функции автозаполнения, и она должна быть быстрой. Предложения должны возвращаться славным и быстрым. Мне нужно посмотреть 3 разных поля для ответа с помощью оператора LIKE. См. Подробности ниже.Хранимая процедура 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, если я допустил некоторые ошибки в своих расчетах, но, надеюсь, вы получили эту идею. - 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

Смежные вопросы