Wow, prawidłowa odpowiedź „Nie zezwalaj na wartości NULL, kiedy nie musisz, ponieważ obniżają one wydajność” to jakoś ostatnia ocena. Będę głosować i opracowywać. Gdy RDBMS zezwala na wartości NULL dla niesparowanej kolumny, kolumna ta jest dodawana do mapy bitowej, która śledzi, czy wartość jest równa NULL dla każdego wiersza. Zatem dodając zdolność NULL do kolumny w tabeli, w której wszystkie kolumny nie zezwalają na wartości NULL, zwiększasz przestrzeń dyskową wymaganą do zapisania tabeli. Ponadto wymaga się od RDBMS odczytu i zapisu mapy bitowej, co obniża wydajność wszystkich operacji.
Ponadto w wielu przypadkach zezwolenie na wartości NULL spowoduje uszkodzenie 3NF. Chociaż nie jestem zwolennikiem 3NF, jak wielu moich kolegów, rozważ następujący scenariusz:
W tabeli Person znajduje się kolumna o nazwie DateOfDeath, która ma wartość null. Jeśli dana osoba umarła, zostanie ona wypełniona datą śmierci, w przeciwnym razie pozostanie NULL. Istnieje również niezerowa kolumna bitowa o nazwie IsAlive. Ta kolumna ma wartość 1, jeśli osoba żyje, i 0, jeśli osoba nie żyje. Zdecydowana większość procedur przechowywanych korzysta z kolumny IsAlive, obchodzi ich tylko to, czy dana osoba żyje, a nie ich DateOfDeath.
Jednak kolumna IsAlive łamie normalizację bazy danych, ponieważ można ją całkowicie uzyskać z DateOfDeath. Ale ponieważ IsAlive jest wbudowane w większość SP, prostym rozwiązaniem jest sprawienie, aby DateOfDeath nie miało wartości zerowej, i przypisanie wartości domyślnej do kolumny w przypadku, gdy osoba nadal żyje. Nieliczne SP, które używają DateOfDeath, mogą następnie zostać przepisane, aby sprawdzić kolumnę IsAlive i honorować DateOfDeath tylko wtedy, gdy dana osoba nie żyje. Ponownie, ponieważ większość SP interesuje się tylko IsAlive (nieco), a nie DateOfDeath (data) przy użyciu tego wzorca znacznie przyspiesza dostęp.
Przydatnym skryptem T-SQL do znajdowania zerowalnych kolumn bez wartości NULL we wszystkich schematach jest:
select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
from sys.columns c
inner join sys.tables t ON c.object_id = t.object_id
inner join sys.schemas s ON s.schema_id = t.schema_id
where c.is_nullable = 1 AND c.is_computed = 0
order by s.name, t.name, c.name;
Jeśli uruchomisz to na kopii produkcyjnej bazy danych, możesz znaleźć kolumny oznaczone przez programistów jako zezwalające na wartości NULL, które w praktyce nie mają wartości NULL. Zdecydowana większość z nich może być oznaczona jako NOT NULL, co zwiększa wydajność i zmniejsza przestrzeń dyskową.
Może nie być możliwe wyeliminowanie wszystkich wartości NULL we wszystkich tabelach i nadal mieć czysty wygląd, ale istnieje znaczna zaleta w eliminowaniu jak największej liczby wartości NULL. Optymalizator działa znacznie szybciej z tymi informacjami, a jeśli możesz wyeliminować wszystkie wartości NULL w tabeli, możesz odzyskać znaczną ilość miejsca do przechowywania.
Wiem, że wydajność nie jest czymś, o czym DBA myślą tak dużo, ale możesz wrzucić rozwiązanie tylko ograniczoną ilość pamięci i mocy procesora, w pewnym momencie będziesz musiał zacząć myśleć o logicznym i fizycznym projekcie .
Zauważ też, że dotyczy to tylko prawdziwych RDBMS i opieram techniczną część moich odpowiedzi na SQL Server. Wymieniony T-SQL do wyszukiwania zerowalnych kolumn bez wartości null pochodzi również z SQL Server.