Медленно выполняемый запрос Sql Server

#sql-server #performance

#sql-сервер #Производительность

Вопрос:

У меня есть следующий запрос:

 DECLARE @CompanyId bigint
DECLARE @SearchText nvarchar(4000)
SET @CompanyId=160
SET @SearchText='863%'
SELECT j.Id FROM Job (NOLOCK) j WHERE (j.Deleted = 0 AND j.CompanyId = @CompanyId) 
    AND (j.Name LIKE @SearchText OR j.DisplayId LIKE @SearchText OR j.ClaimNumber LIKE @SearchText) 
UNION SELECT j.Id FROM Job (NOLOCK) j INNER JOIN Address (NOLOCK) a ON a.Id = j.AddressId 
    WHERE j.Deleted = 0 AND j.CompanyId = @CompanyId 
    AND a.SearchAddress LIKE @SearchText 
UNION SELECT j.Id FROM Job (NOLOCK) j INNER JOIN Contact (NOLOCK) c ON c.Id = j.CustomerId 
    WHERE j.Deleted = 0 AND j.CompanyId = @CompanyId 
    AND c.SearchName LIKE @SearchText
  

для выполнения которого иногда требуется более 10 секунд.

Наша база данных довольно маленькая, и я не думаю, что это должно занять так много времени, и мне интересно, правильно ли я сформулировал этот запрос или мне следует его изменить?

Из того, что я прочитал, я не верю, что реализация полнотекстового поиска сильно поможет, поскольку это прямые сравнения, верно?

Кроме того, учитывая этот запрос, я надеюсь, что он будет искать только адреса и контакты, принадлежащие заданиям, где CompanyID=@CompanyID и deleted= 0? Или он будет искать все адреса и контакты во всей базе данных, а затем фильтровать на основе критериев задания?

Ответ №1:

Другая вещь, которую вы, возможно, захотите рассмотреть, — это объединение всех выборок в один оператор. Что происходит прямо сейчас, так это то, что вы выполняете три полных сканирования индекса, а затем отфильтровываете любые дубликаты (с объединением). В этом случае может быть быстрее один раз просмотреть таблицу и использовать ‘или’ в вашем запросе.

Чтобы ответить на ваш последний вопрос, прямо сейчас, при полном сканировании индекса, Sql server работает более последовательно. Итак, он будет смотреть на первую точку данных. Если j.deleted = 0, то sql продолжит выполнение следующего условия, которое вы включили. Итак, он проверяет, соответствует ли CompanyID = @CompanyID. Если это так, он переходит к проверке следующего условия.

Изменение вашего запроса на do seeks позволяет sql быстрее и проще оттачивать то, что вы ищете.

 DECLARE @CompanyId bigint
DECLARE @SearchText nvarchar(4000)

SET @CompanyId=160
SET @SearchText='863%'

SELECT j.Id
FROM Job (NOLOCK) j
WHERE j.Deleted = 0 
  AND j.CompanyId = @CompanyId 
  AND ( j.Name LIKE @SearchText
    OR  j.DisplayId LIKE @SearchText
    OR  j.ClaimNumber LIKE @SearchText
    OR (exists  select 1
                From address (nolock a)
                Where a.id = j.addressid
                and     a.SearchAddress like @SearchText)
    or (exists select 1
                From contact (nolock) c
                Where c.id=j.customerid
                and     c.SearchName like @SearchText)
    )
  

Комментарии:

1. Изменение этого запроса делает его практически мгновенным!! Вау, большое вам спасибо!!

Ответ №2:

 @SearchText='863%'
  

Вызовет полное сканирование индекса, поскольку он ищет эту строку в любом месте индекса. Если бы строка поиска была чем-то вроде ‘02863%’, она могла бы использовать поиск по индексу и быть более эффективной, потому что у нее есть с чего начать.

Было бы очень полезно, если бы вы могли опубликовать план выполнения.