У меня есть следующее индексированное представление, определенное в SQL Server 2008 (вы можете загрузить рабочую схему из gist для тестирования):
CREATE VIEW dbo.balances
WITH SCHEMABINDING
AS
SELECT
user_id
, currency_id
, SUM(transaction_amount) AS balance_amount
, COUNT_BIG(*) AS transaction_count
FROM dbo.transactions
GROUP BY
user_id
, currency_id
;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_balances_user_id_currency_id
ON dbo.balances (
user_id
, currency_id
);
GO
user_id
, currency_id
и transaction_amount
все определены как NOT NULL
столбцы в dbo.transactions
. Однако когда я смотрю на определение представления в обозревателе объектов Management Studio, оно помечает столбцы как balance_amount
и transaction_count
как NULL
доступные в представлении.
Я принял взглянуть на несколько дискуссий, это один является наиболее важным из них, которые предполагают некоторую перестановку функций может помочь SQL Server признать , что столбец вид всегда NOT NULL
. Однако в моем случае такая перетасовка невозможна, так как выражения в агрегатных функциях (например, ISNULL()
над over SUM()
) не допускаются в индексированных представлениях.
Можно ли как-то помочь SQL Server распознать это
balance_amount
иtransaction_count
можноNOT NULL
ли?Если нет, следует ли мне
NULL
опасаться, что эти столбцы ошибочно определены как -able?Две проблемы, о которых я мог подумать:
- Любые объекты приложения, сопоставленные с представлением сальдо, получают неверное определение сальдо.
- В очень ограниченных случаях определенные оптимизации не доступны Оптимизатору запросов, так как он не имеет гарантии, исходя из того, что эти два столбца доступны
NOT NULL
.
Является ли что-то из этого серьезным? Есть ли еще какие-то проблемы, которые я должен иметь в виду?
источник
Ответы:
Мне кажется, что у SQL Server есть общее предположение о том, что агрегат может производить
null
даже если поля, с которыми он работает, являютсяnot null
. Это очевидно верно в некоторых случаях:И это также верно в обобщенных версиях,
group by
какcube
Этот более простой тестовый пример иллюстрирует тот факт, что любой агрегат интерпретируется как обнуляемый:
IMO, это ограничение (хотя и незначительное) SQL Server - некоторые другие СУБД позволяют создавать определенные ограничения для представлений, которые не применяются и существуют только для того, чтобы дать подсказки оптимизатору, хотя я думаю, что «уникальность» более вероятна помочь в создании хорошего плана запроса, чем «обнуляемость»
Если обнуляемость столбца важна, возможно, для использования с ORM, рассмотрите возможность помещения индексированного представления в другое представление, которое просто гарантирует необнуляемость, используя
ISNULL
:источник
Я не думаю, что есть какой-то способ заставить SQL Server распознавать эти столбцы как необнуляемые, даже если они явно нет. Например, вы можете попытаться изменить порядок определения
ISNULL
/COALESCE
вокруг выражения внутриSUM()
, но это не поможет.Я также не верю, что есть какие-то оптимизации, которые вы пропустите - эти столбцы в настоящее время не индексируются, поэтому не похоже, чтобы оптимизатор мог выбрать другой метод доступа для определения, скажем, всех
balance_amount
значений> 10000. может возникнуть ситуация, когда, если вы создадите некластеризованный индекс для одного из этих столбцов, вы можете получить более точные оценки, чем если бы индекс отсутствовал, но это не имеет ничего общего с обнуляемостью.Я не был бы слишком обеспокоен этим с точки зрения производительности. Я вернулся и посмотрел на несколько индексированных представлений, созданных мной за эти годы, и все эти столбцы агрегирования обнуляются. Они работают просто отлично.
Что касается сопоставления объектов, я бы не стал слишком беспокоиться об этом. Поскольку приложение не может обновить индексированное представление, не имеет значения, если оно считает, что это
balance_amount
может бытьnull
. Он никогда не получитnull
, и не может попытаться написатьnull
, так<shrug>
.источник