Eu tenho a seguinte visão indexada definida no SQL Server 2008 (você pode baixar um esquema de trabalho do gist para fins de teste):
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
, e transaction_amount
são todos definidos como NOT NULL
colunas em dbo.transactions
. No entanto, quando olho para a definição de exibição no Object Explorer do Management Studio, ela marca ambas as colunas balance_amount
e transaction_count
como habilitadas na exibição.NULL
Eu dei uma olhada em várias discussões, sendo esta a mais relevante delas, que sugere que algumas funções embaralhadas podem ajudar o SQL Server a reconhecer que uma coluna de exibição é sempre NOT NULL
. No entanto, esse embaralhamento não é possível no meu caso, uma vez que expressões em funções agregadas (por exemplo, an ISNULL()
over the SUM()
) não são permitidas em exibições indexadas.
Existe alguma maneira de ajudar o SQL Server a reconhecer isso
balance_amount
etransaction_count
serNOT NULL
capaz?Caso contrário, devo me preocupar com o fato de essas colunas serem identificadas erroneamente como
NULL
-able?As duas preocupações que eu poderia pensar são:
- Qualquer objeto de aplicativo mapeado para a exibição de saldos está obtendo uma definição incorreta de um saldo.
- Em casos muito limitados, certas otimizações não estão disponíveis para o Query Optimizer, uma vez que não há garantia da exibição de que essas duas colunas são
NOT NULL
.
Alguma dessas preocupações é importante? Existem outras preocupações que devo ter em mente?
Parece-me que o SQL Server tem uma suposição geral de que um agregado pode produzir um
null
mesmo se o(s) campo(s) em que opera foremnot null
. Isso é obviamente verdade em certos casos:E também é verdade nas versões generalizadas de
group by
comocube
Este caso de teste mais simples ilustra o ponto em que qualquer agregação é interpretada como anulável:
IMO, esta é uma limitação (embora menor) do SQL Server - alguns outros RDBMSs permitem a criação de certas restrições em visualizações que não são aplicadas e existem apenas para fornecer pistas ao otimizador, embora eu ache que 'singularidade' é mais provável ajuda na geração de um bom plano de consulta do que 'nullability'
Se a nulidade da coluna for importante, talvez para uso com um ORM, considere agrupar a exibição indexada em outra exibição que simplesmente garanta a não nulidade usando
ISNULL
:Não acho que haja como forçar o SQL Server a reconhecer essas colunas como não anuláveis, mesmo que elas claramente não sejam. Você pode tentar mudar a ordem de como você define
ISNULL
/COALESCE
em torno da expressão dentroSUM()
de , por exemplo, mas não vai ajudar.Também não acredito que haja otimizações que você perderá - essas colunas não estão indexadas no momento, portanto, não é como se o otimizador pudesse escolher um método de acesso diferente para determinar, digamos, todos os
balance_amount
valores > 10.000. pode ser uma situação em que, se você criar um índice não clusterizado em uma dessas colunas, poderá obter estimativas um pouco melhores do que se o índice não estiver lá, mas isso não tem nada a ver com a nulidade.Eu não ficaria muito preocupado com isso do ponto de vista do desempenho. Voltei e olhei para um monte de exibições indexadas que criei ao longo dos anos e essas colunas de agregação são todas anuláveis. Eles funcionam muito bem.
No que diz respeito ao mapeamento de objetos, novamente, eu não ficaria muito preocupado com isso. Como o aplicativo não pode atualizar a exibição indexada, não importa se ele pensa que
balance_amount
pode sernull
. Ele nunca receberá umnull
, e não pode tentar escrever umnull
, então<shrug>
.