У меня есть два индексированных представления, v_First
и v_Second
.Эти представления прекрасно работают, когда у меня есть предложение WHERE
, которое фильтрует только на основе одного из этих представлений, однако, как только у меня есть критерии фильтрации, основанные на обоих представлениях, я получаю два сканирования кластеризованного индекса и в результате низкую производительность.
Мой запрос:
SELECT * FROM dbo.v_First (NOEXPAND)
JOIN dbo.v_Second (NOEXPAND)
ON dbo.v_First.id = dbo.v_Second.id
WHERE
dbo.v_First.Firstname = 'JUSTIN'
OR dbo.v_Second.Surname = 'JUSTIN'
Если я закомментирую одно из двух приведенных выше предложений WHERE
, я получу поиски, и запрос выполнится, и я знаю, что по отдельности у меня определены правильные индексы.
Почему запрос не выполняется при фильтрации по нескольким индексированным представлениям и что я могу сделать, чтобы исправить это?
(Извините, я не могу опубликовать планы выполнения, они все равно тривиальны- только два сканирования кластеризованного индекса для кластерного индекса двух соответствующих представлений и объединение слиянием)
Обновление:
v_First столбцы:
- ID (bigint, кластеризованный индекс)
- FirstName (varchar (254), некластеризованный индекс)
v_Second столбцы:
- ID (bigint, кластерный индекс)
- Фамилия (varchar (254), некластеризованный индекс)
Все индексы содержат только один столбец.
Обновление, второй:
Я обнаружил, что если предложение OR
изменяется на предложение AND
, запрос выполняется нормально.Я также обнаружил, что если я изменю запрос на использование оператора UNION
вместо OR
, запрос будет выполняться нормально:
SELECT * FROM dbo.v_First (NOEXPAND)
JOIN dbo.v_Second (NOEXPAND)
ON dbo.v_First.ID = dbo.v_Second.ID
WHERE dbo.v_First.Firstname = 'JUSTIN'
UNION SELECT * FROM dbo.v_First (NOEXPAND)
JOIN dbo.v_Second (NOEXPAND)
ON dbo.v_First.ID = dbo.v_Second.ID
WHERE dbo.v_Second.Surname = 'JUSTIN'
Насколько я знаю, эти два запроса должны бытьэквивалентно?
Наконец, я также обнаружил, что использование подзапроса вместо этого также имеет странный эффект, следующий запрос выполняется нормально:
SELECT * FROM dbo.v_First (NOEXPAND)
-- JOIN dbo.v_Second (NOEXPAND)
-- ON dbo.v_First.ID = dbo.v_Second.ID
WHERE dbo.v_First.ID IN
(
SELECT ID FROM dbo.v_Second (NOEXPAND)
WHERE dbo.v_Second.Surname = 'JUSTIN'
)
OR dbo.v_First.Firstname = 'JUSTIN'
Однако, если я раскомментирую JOIN
(так что я могу получить столбцы из второй таблицы в результатах моего запроса), затем я получаю сканирование таблицы по кластерному индексу v_Second (обратите внимание, однако, что это все же лучше, чем в исходном запросе, поскольку он включает только 1 сканирование вместо 2).).
Я очень смущен - что происходит?Кажется, что я могу обойти эти проблемы, «рефакторинг» моего запроса, однако я обеспокоен тем, что не понимаю, что здесь происходит - я бы предпочел избегать внесения изменений, которые я не до конца понимаю.