Чем заменить левое соединение в представлении, чтобы иметь индексированное представление?

У меня есть нормализованные таблицы в базе данных, и для денормализации я создал представление из двух таблиц. Когда я попытался создать кластерный индекс для представления, он не позволил мне, так как представление было создано с левым внешним соединением. Я использовал левое соединение, потому что я хочу, чтобы нулевые значения отображались в результирующем представлении, так же, как это было предложено в этом предыдущем посте.

Вопрос по объединению, где один столбец с одной стороны нулевой

Структура таблицы и отношения очень похожи на то, что было описано в приведенной выше ссылке.

Мне показалось, что я попал в стену, так как не смог преобразовать левое соединение во внутреннее, так как это исключило бы все записи с нулевыми значениями в любом из соединенных столбцов. Мои вопросы:

  1. Почему индексация не допускается для внешних или собственных соединений?
  2. Есть ли какие-либо потери производительности в этом неиндексированном представлении?
  3. Кто-нибудь знает какое-либо решение этой проблемы?

Я только что закончил курс SQL Server вчера, поэтому не знаю, как поступить. Буду признателен за любые комментарии. Приветствия.

5 ответов

Решение

Здесь есть "обходной путь", который включает проверку NULL в соединении и имея NULL значение представления в таблице

Значение NULL

INSERT INTO Father (Father_id, Father_name) values(-255,'No father')

Соединение

JOIN [dbo].[son] s on isnull(s.father_id, -255) = f.father_id

Вот альтернатива. Вы хотите материализованное представление A, не содержащее B. Это не доступно напрямую... поэтому вместо этого материализуйте два представления. Один из всех А и один только А с B. Затем получите только A, не имеющие B, взяв A, кроме B. Это можно сделать эффективно:

Создайте два материализованных представления (mA и mAB) (правка: mA может быть просто базовой таблицей). У mA отсутствует соединение между A и B (таким образом, содержит все точки A [и, следовательно, содержит эти записи БЕЗ совпадений в B]). mAB объединяет A и B (таким образом, содержит только A с B [и, следовательно, исключая эти записи БЕЗ совпадений в B]).

Чтобы получить все A без совпадений в B, замаскируйте те, которые соответствуют:

with ids as (
  select matchId from mA with (index (pk_matchid), noexpand)
  except
  select matchId from mAB with (index (pk_matchid), noexpand)
)
select * from mA a join ids b on a.matchId = b.matchId;

Это должно дать левое анти-полусоединение против ваших кластерных индексов для получения идентификаторов, а кластерный индекс - для получения данных из mA, который вы ищете.

По сути, вы сталкиваетесь с основным правилом, согласно которому SQL гораздо лучше справляется с данными, которые там есть, чем с данными, которых нет. Материализуя два источника, вы получаете несколько привлекательных опций на основе набора. Вы должны сопоставить стоимость этих взглядов с этими достижениями самостоятельно.

Я не думаю, что есть хороший обходной путь. Что вы можете сделать по этому поводу, так это создать реальную таблицу из представления и установить для нее индексы. Это можно сделать с помощью хранимой процедуры, которая регулярно вызывается при обновлении данных.

Select * 
into <REAL_TABLE>
From <VIEW>

create CLUSTERED index <INDEX_THE_FIELD> on <REAL_TABLE>(<THE_FIELD>)

Но это только заслуживающий внимания подход, если данные не обновляются каждые несколько секунд.

Логически вы делаете два отдельных запроса. "A LEFT JOIN B" - это просто сокращение для "(A JOIN B) UNION A"

Первый запрос - это таблица A, внутренне соединенная с таблицей B. Это получает индексированное представление, так как здесь все тяжелые работы выполняются.

Второй запрос - это просто таблица A, в которой любой из столбцов соединения имеет значение null. Создайте представление, которое выдает те же выходные столбцы, что и первый запрос, и дополняет их нулями.

Просто объедините два результата, прежде чем возвращать их. Нет необходимости в обходном пути.

Я поработаю над ответом на 1, а пока:

[2]. Представление будет не более и не менее производительным, чем эквивалентный запрос для таблиц с отклонением. Все обычные советы применимы к наличию индексов покрытия, предпочтительно индекса для соединенных столбцов и т. Д.

[3]. Там нет реального обхода. Большинство ограничений на индексированные представления существуют по очень веским причинам, как только вы их изучите.

Я бы просто создал представление и больше ничего не делал, если не было конкретной проблемы с производительностью.

Я постараюсь добавить ответ на 1, как только я восстановил его в своем собственном уме.

Другие вопросы по тегам