#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%’, она могла бы использовать поиск по индексу и быть более эффективной, потому что у нее есть с чего начать.
Было бы очень полезно, если бы вы могли опубликовать план выполнения.