Ich habe die folgende indizierte Ansicht in SQL Server 2008 definiert (Sie können ein Arbeitsschema zu Testzwecken von gist herunterladen ):
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
und transaction_amount
sind alle als NOT NULL
Spalten in definiert dbo.transactions
. Aber wenn ich mir die Sichtdefinition in Management Studio Object Explorer, es Markierungen sowohl balance_amount
und transaction_count
als NULL
-able Spalten in der Ansicht.
Ich habe mir mehrere Diskussionen angesehen, von denen diese die relevanteste ist. Diese weisen darauf hin, dass durch das Mischen von Funktionen SQL Server möglicherweise erkennt, dass eine Ansichtsspalte immer vorhanden ist NOT NULL
. In meinem Fall ist ein solches Mischen jedoch nicht möglich, da Ausdrücke für Aggregatfunktionen (z. B. ein ISNULL()
Over-Over SUM()
) in indizierten Ansichten nicht zulässig sind .
Gibt es eine Möglichkeit, SQL Server erkennen , dass helfen kann ,
balance_amount
undtransaction_count
sindNOT NULL
-able?Wenn nicht, sollte ich Bedenken haben, dass diese Spalten fälschlicherweise als
NULL
-able identifiziert werden ?Die zwei Bedenken, an die ich denken könnte, sind:
- Alle Anwendungsobjekte, die der Saldenansicht zugeordnet sind, erhalten eine falsche Definition einer Bilanz.
- In sehr begrenzten Fällen stehen dem Abfrageoptimierer bestimmte Optimierungen nicht zur Verfügung, da aus der Sicht dieser beiden Spalten keine Garantie besteht
NOT NULL
.
Ist eines dieser Probleme eine große Sache? Gibt es noch andere Bedenken, die ich berücksichtigen sollte?
quelle
Antworten:
Es scheint mir, dass SQL Server pauschal davon ausgeht, dass ein Aggregat ein gerades Ergebnis erzielen kann,
null
wenn es sich um die Felder handelt, mit denen es arbeitetnot null
. Dies gilt offensichtlich in bestimmten Fällen:Und gilt auch für die verallgemeinerten Versionen von
group by
likecube
Dieser einfachere Testfall veranschaulicht den Punkt, an dem jedes Aggregat als nullbar interpretiert wird:
IMO ist dies eine (wenn auch geringfügige) Einschränkung von SQL Server. Einige andere RDBMS ermöglichen die Erstellung bestimmter Einschränkungen für Ansichten, die nicht erzwungen werden und nur existieren, um dem Optimierer Hinweise zu geben, obwohl ich der Meinung bin, dass "Eindeutigkeit" wahrscheinlicher ist Hilfe bei der Erstellung eines guten Abfrageplans als "Nullability"
Wenn die Nullbarkeit der Spalte wichtig ist, möglicherweise für die Verwendung mit einem ORM, sollten Sie die indizierte Ansicht in eine andere Ansicht einschließen, die einfach die Nicht-Nullfähigkeit garantiert, indem Sie
ISNULL
:quelle
Ich glaube nicht, dass Sie SQL Server auf irgendeine Weise zwingen können, diese Spalten als nicht nullbar zu erkennen, obwohl dies eindeutig nicht der Fall ist. Sie können versuchen , die Reihenfolge zu ändern , wie definieren Sie
ISNULL
/COALESCE
um den Ausdruck im InnernSUM()
, zum Beispiel, aber es wird nicht zu Hilfe.Ich glaube auch nicht, dass es Optimierungen gibt, die Sie verpassen werden - diese Spalten sind derzeit nicht indiziert, daher kann der Optimierer keine andere Zugriffsmethode auswählen, um beispielsweise alle
balance_amount
Werte> 10000 zu bestimmen Wenn Sie einen nicht gruppierten Index für eine dieser Spalten erstellen, erhalten Sie möglicherweise etwas bessere Schätzungen als wenn der Index nicht vorhanden ist. Dies hat jedoch nichts mit der Nullfähigkeit zu tun.Aus Performance-Sicht wäre ich darüber nicht allzu besorgt. Ich ging zurück und sah mir eine Reihe von indizierten Ansichten an, die ich im Laufe der Jahre erstellt habe. Diese Aggregationsspalten sind alle nullwertfähig. Sie funktionieren gut.
Auch bei der Objektzuordnung würde ich mir darüber keine Sorgen machen. Da die Anwendung die indizierte Ansicht nicht aktualisieren kann, spielt es keine Rolle, ob dies
balance_amount
möglich istnull
. Es wird niemals eine erhaltennull
, und es kann nicht versuchen, eine zu schreibennull
, also<shrug>
.quelle