Чем заменить левое соединение в представлении, чтобы иметь индексированное представление?
У меня есть нормализованные таблицы в базе данных, и для денормализации я создал представление из двух таблиц. Когда я попытался создать кластерный индекс для представления, он не позволил мне, так как представление было создано с левым внешним соединением. Я использовал левое соединение, потому что я хочу, чтобы нулевые значения отображались в результирующем представлении, так же, как это было предложено в этом предыдущем посте.
Вопрос по объединению, где один столбец с одной стороны нулевой
Структура таблицы и отношения очень похожи на то, что было описано в приведенной выше ссылке.
Мне показалось, что я попал в стену, так как не смог преобразовать левое соединение во внутреннее, так как это исключило бы все записи с нулевыми значениями в любом из соединенных столбцов. Мои вопросы:
- Почему индексация не допускается для внешних или собственных соединений?
- Есть ли какие-либо потери производительности в этом неиндексированном представлении?
- Кто-нибудь знает какое-либо решение этой проблемы?
Я только что закончил курс 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, как только я восстановил его в своем собственном уме.