Mam następujący widok indeksowany zdefiniowany w SQL Server 2008 (możesz pobrać działający schemat z gist do celów testowych):
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
i transaction_amount
wszystkie są zdefiniowane jako NOT NULL
kolumny w dbo.transactions
. Jednak kiedy patrzę na definicji widoku w zarządzaniu Studio Object Explorer, to znaki obu balance_amount
i transaction_count
jak NULL
-able kolumn w widoku.
Rzuciłem okiem na kilka dyskusji, z których ta jest najbardziej odpowiednia, sugerując, że pewne tasowanie funkcji może pomóc SQL Serverowi rozpoznać, że kolumna widoku jest zawsze NOT NULL
. W moim przypadku takie tasowanie nie jest możliwe, ponieważ wyrażenia dotyczące funkcji agregujących (np. ISNULL()
Ponad SUM()
) nie są dozwolone w widokach indeksowanych.
Czy jest jakiś sposób, w jaki mogę pomóc SQL Serverowi to rozpoznać
balance_amount
i czytransaction_count
możnaNOT NULL
?Jeśli nie, to czy powinienem mieć jakiekolwiek obawy, że te kolumny zostaną omyłkowo zidentyfikowane jako możliwe
NULL
?Dwa problemy, o których mogłem pomyśleć, to:
- Wszelkie obiekty aplikacji odwzorowane na widok sald otrzymują niepoprawną definicję salda.
- W bardzo ograniczonych przypadkach niektóre optymalizacje nie są dostępne dla Optymalizatora zapytań, ponieważ nie ma gwarancji z widoku, że te dwie kolumny są
NOT NULL
.
Czy któraś z tych kwestii jest ważna? Czy są jeszcze jakieś obawy, o których powinienem pamiętać?
źródło
Odpowiedzi:
Wydaje mi się, że SQL Server ma ogólne założenie, że agregacja może wygenerować
null
nawet, jeśli pola, na których operuje, sąnot null
. Jest to oczywiście prawda w niektórych przypadkach:Dotyczy to również uogólnionych wersji programu
group by
likecube
Ten prostszy przypadek testowy pokazuje, że każdy agregat jest interpretowany jako zerowalny:
IMO jest to ograniczenie (choć niewielkie) SQL Server - niektóre inne RDBMS pozwalają na tworzenie pewnych ograniczeń w widokach, które nie są egzekwowane i istnieją tylko po to, aby dać wskazówki optymalizatorowi, chociaż myślę, że „wyjątkowość” jest bardziej prawdopodobna pomoc w generowaniu dobrego planu zapytań niż „zerowalność”
Jeśli zerowalność kolumny jest ważna, być może do użycia z ORM, rozważ zawinięcie indeksowanego widoku w innym widoku, który po prostu gwarantuje brak zerowania przy użyciu
ISNULL
:źródło
Nie sądzę, aby można było zmusić program SQL Server do rozpoznania tych kolumn jako zerowalne, nawet jeśli najwyraźniej nie są. Możesz na przykład spróbować zmienić kolejność definiowania
ISNULL
/COALESCE
otaczania wyrażenia w środkuSUM()
, ale to nie pomoże.Nie wierzę też, że istnieją jakieś optymalizacje, których przegapisz - te kolumny nie są obecnie indeksowane, więc to nie jest tak, że optymalizator może wybrać inną metodę dostępu, aby określić, powiedzmy, wszystkie
balance_amount
wartości> 10000. Tam może się zdarzyć, że jeśli utworzysz indeks nieklastrowany w jednej z tych kolumn, możesz uzyskać nieco lepsze oszacowania niż w przypadku braku tego indeksu, ale nie ma to nic wspólnego z zerowalnością.Nie martwiłbym się tym zbytnio z punktu widzenia wydajności. Wróciłem i spojrzałem na kilka indeksowanych widoków, które stworzyłem przez lata i wszystkie te kolumny agregacji są zerowalne. Występują dobrze.
Jeśli chodzi o mapowanie obiektów, znowu nie martwiłbym się tym. Ponieważ aplikacja nie może zaktualizować widoku indeksowanego, nie ma znaczenia, czy tak
balance_amount
jestnull
. Nigdy nie otrzymanull
i nie może spróbować napisaćnull
, więc<shrug>
.źródło