J'ai la vue indexée suivante définie dans SQL Server 2008 (vous pouvez télécharger un schéma de travail à partir de gist à des fins de test):
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
et transaction_amount
sont tous définis comme des NOT NULL
colonnes dans dbo.transactions
. Cependant, lorsque je regarde la définition de la vue dans l'Explorateur d'objets de Management Studio, elle marque les deux colonnes balance_amount
et en transaction_count
tant que NULL
-able dans la vue.
J'ai jeté un coup d'œil à plusieurs discussions, celle-ci étant la plus pertinente d'entre elles, qui suggèrent qu'un mélange des fonctions peut aider SQL Server à reconnaître qu'une colonne de vue est toujours NOT NULL
. Un tel mélange n'est pas possible dans mon cas, cependant, car les expressions sur les fonctions d'agrégation (par exemple un ISNULL()
sur le SUM()
) ne sont pas autorisées dans les vues indexées.
Est - il possible que je peux aider SQL Server reconnaître que
balance_amount
ettransaction_count
sontNOT NULL
able?Sinon, devrais-je craindre que ces colonnes soient identifiées par erreur comme étant
NULL
-able?Les deux préoccupations auxquelles je pouvais penser sont:
- Tous les objets d'application mappés à la vue des soldes obtiennent une définition incorrecte d'un solde.
- Dans des cas très limités, certaines optimisations ne sont pas disponibles pour l'Optimiseur de requête car il n'a pas de garantie de la vue que ces deux colonnes le sont
NOT NULL
.
L'une ou l'autre de ces préoccupations est-elle un gros problème? Y a-t-il d'autres préoccupations que je dois garder à l'esprit?
la source
Réponses:
Il me semble que SQL Server a une hypothèse générale qu'un agrégat peut produire un
null
même si le ou les champs sur lesquels il opère le sontnot null
. C'est évidemment vrai dans certains cas:Et est également vrai dans les versions généralisées de
group by
commecube
Ce cas de test plus simple illustre le point que tout agrégat est interprété comme pouvant être annulé:
OMI, il s'agit d'une limitation (quoique mineure) de SQL Server - certains autres SGBDR permettent la création de certaines contraintes sur les vues qui ne sont pas appliquées et n'existent que pour donner des indices à l'optimiseur, bien que je pense que "l'unicité" est plus susceptible de aider à générer un bon plan de requête que la «nullité»
Si la valeur NULL de la colonne est importante, peut - être pour une utilisation avec un ORM, pensez à envelopper la vue indexée dans une autre vue que le simple garantit l'utilisation de non-valeur NULL
ISNULL
:la source
Je ne pense pas qu'il soit possible de forcer SQL Server à reconnaître ces colonnes comme non nulles, même si elles ne le sont clairement pas. Vous pouvez essayer de changer l'ordre dans lequel vous définissez
ISNULL
/COALESCE
autour de l'expression à l' intérieurSUM()
, par exemple, mais cela ne va pas aider.Je ne crois pas non plus qu'il y ait des optimisations que vous allez manquer - ces colonnes ne sont pas actuellement indexées, donc ce n'est pas comme si l'optimiseur peut choisir une méthode d'accès différente pour déterminer, disons, toutes les
balance_amount
valeurs> 10000. Là peut être une situation où si vous créez un index non clusterisé sur l'une de ces colonnes, vous pourriez obtenir des estimations légèrement meilleures que si l'index n'est pas là, mais cela n'a rien à voir avec la nullité.Je ne serais pas trop inquiet à ce sujet du point de vue des performances. Je suis retourné en arrière et j'ai regardé un tas de vues indexées que j'ai créées au fil des ans et ces colonnes d'agrégation sont toutes annulables. Ils fonctionnent très bien.
En ce qui concerne le mappage d'objets, encore une fois, je ne serais pas trop inquiet à ce sujet. Étant donné que l'application ne peut pas mettre à jour la vue indexée, peu importe si elle pense que
balance_amount
peut êtrenull
. Il ne va jamais recevoirnull
, et il ne peut pas essayer d'écrire unnull
, donc<shrug>
.la source