Pamiętam, jak czytałem ten jeden artykuł na temat projektowania baz danych i pamiętam również, że powinieneś mieć właściwości pola NOT NULL. Nie pamiętam jednak, dlaczego tak było.
Mogę tylko myśleć o tym, że jako twórca aplikacji nie musiałbyś testować NULL i możliwej nieistniejącej wartości danych (na przykład pusty ciąg znaków dla łańcuchów).
Ale co robisz w przypadku dat, godziny i godziny (SQL Server 2008)? Będziesz musiał skorzystać z jakiejś historycznej lub oddolnej daty.
Jakieś pomysły na ten temat?
database-design
null
Thomas Stringer
źródło
źródło
Odpowiedzi:
Myślę, że pytanie jest źle sformułowane, ponieważ sformułowanie sugeruje, że już zdecydowałeś, że wartości NULL są złe. Być może miałeś na myśli „Czy powinniśmy dopuszczać wartości NULL?”
Tak czy inaczej, oto moje zdanie na ten temat: Myślę, że wartości NULL są dobre. Gdy zaczniesz zapobiegać wartościom NULL tylko dlatego, że „wartości NULL są złe” lub „wartości NULL są trudne”, zaczniesz tworzyć dane. Na przykład, co jeśli nie znasz mojej daty urodzenia? Co zamierzasz umieścić w kolumnie, dopóki się nie dowiesz? Jeśli jesteś kimś w rodzaju wielu przeciwników NULL, wejdziesz do 1900-01-01. Teraz zostanę umieszczony na oddziale geriatrycznym i prawdopodobnie otrzymam telefon z mojej lokalnej stacji prasowej gratulując mi długiego życia, prosząc mnie o sekrety tak długiego życia itp.
Jeśli można wprowadzić wiersz, w którym możliwe jest, że nie znasz wartości kolumny, myślę, że NULL ma o wiele większy sens niż wybranie jakiejkolwiek arbitralnej wartości tokena reprezentującej fakt, że jest nieznana - wartość, którą inni będą muszę już wiedzieć, inżynierii wstecznej lub poprosić, aby dowiedzieć się, co to znaczy.
Jest jednak równowaga - nie każda kolumna w twoim modelu danych powinna mieć wartość zerową. Często w formularzu są pola opcjonalne lub informacje, które w przeciwnym razie nie są gromadzone w momencie tworzenia wiersza. Ale to nie znaczy, że możesz odroczyć zapełnianie wszystkich danych. :-)
Zdolność do używania NULL może być ograniczona przez kluczowe wymagania w prawdziwym życiu. Na przykład w dziedzinie medycyny wiedza o tym, dlaczego wartość jest nieznana , może być sprawą życia lub śmierci . Czy częstość akcji serca jest NULL, ponieważ nie było tętna lub dlatego, że jeszcze go nie mierzyliśmy? W takim przypadku, czy możemy wstawić NULL w kolumnie tętna i mieć notatki lub inną kolumnę z NULL-z powodu powodu?
Nie bój się wartości NULL, ale bądź gotów nauczyć się lub dyktować, kiedy i gdzie powinny być używane, a kiedy i gdzie nie powinny.
źródło
birth_date
której przechowujesz daty urodzenia? Jeśli data urodzenia jest nieznana, po prostu nie wstawiaj daty urodzeniabirth_date
. Nulls to katastrofa.1900-01-01
aby uniknąć NULL wartości daty / godziny? Ok więc. Również NULL = nieznany i nieznany = fałszywy. Nie jestem pewien, jakie problemy mogą powodować inne niż ludzie, którzy nie rodzą się, wiedząc o tym (tak jakby nie rodzili się, wiedząc wiele rzeczy związanych ze złożonym RDBMS). Znów machając rękami i mówiąc „Problem! Katastrofa!” tak nie robi.Ustalone powody to:
NULL nie jest wartością, a zatem nie ma wewnętrznego typu danych. Wartości NULL wymagają specjalnej obsługi w każdym miejscu, gdy kod, który w innym przypadku opiera się na rzeczywistych typach, może również otrzymać niepoprawny NULL.
NULL łamie logikę dwóch wartości (znana prawda lub fałsz) i wymaga logiki trzech wartości. Jest to o wiele bardziej skomplikowane nawet w przypadku prawidłowego wdrożenia i jest z pewnością słabo zrozumiane przez większość DBA i prawie wszystkie inne niż DBA. W rezultacie pozytywnie zachęca do wielu subtelnych błędów w aplikacji.
Znaczenie semantyczne dowolnego określonego NULL pozostawia się aplikacji , w przeciwieństwie do rzeczywistych wartości.
Semantyka, taka jak „nie dotyczy” i „nieznany” i „wartownik”, są powszechne, są też inne. Są często używane jednocześnie w tej samej bazie danych, nawet w tej samej relacji; i są oczywiście niewytłumaczalne, nierozróżnialne i niekompatybilne .
Nie są one konieczne do relacyjnych baz danych , jak argumentowano w „Jak radzić sobie z brakującymi informacjami bez wartości zerowych” . Dalsza normalizacja jest oczywistym pierwszym krokiem, aby spróbować pozbyć się tabeli NULL.
To nie znaczy, że NULL nigdy nie powinien być dozwolony. To nie twierdzą, że istnieje wiele dobrych powodów, aby uniemożliwić NULL gdziekolwiek to możliwe.
Co istotne, przemawia za tym, aby bardzo się starać - dzięki lepszemu projektowaniu schematów i lepszym silnikom baz danych, a nawet lepszym językom baz danych - aby umożliwić częstsze unikanie NULL.
Fabian Pascal odpowiada na szereg argumentów w „Nulls Nullified” .
źródło
Nie zgadzam się, wartości zerowe są istotnym elementem projektowania baz danych. Alternatywą, jak również wspomniałeś, byłoby rozpowszechnianie znanych wartości reprezentujących brakujące lub nieznane. Problem polega na tym, że zero jest tak szeroko niezrozumiane, w wyniku czego jest stosowane niewłaściwie.
IIRC, Codd zasugerował, że obecna implementacja wartości zerowej (co oznacza brak / brak) może zostać ulepszona poprzez posiadanie dwóch pustych znaczników zamiast jednego, „nieobecny, ale odpowiedni” i „nieobecny i nie dotyczy”. Nie mogę przewidzieć, w jaki sposób projekty relacyjne zostałyby przez to ulepszone osobiście.
źródło
null
i zdefiniowanej przez użytkownika logiki wielowartościowej, aby iść z nimi: pZacznę od stwierdzenia, że nie jestem DBA, jestem programistą na pamięć i utrzymuję i aktualizujemy nasze bazy danych w oparciu o nasze potrzeby. Biorąc to pod uwagę, miałem to samo pytanie z kilku powodów.
Bardzo długo spędzam przesiewając w Internecie mnóstwo odpowiedzi, komentarzy, artykułów i porad. Nie trzeba dodawać, że większość informacji dotyczyła odpowiedzi @ AaronBertrand. Dlatego czułem potrzebę odpowiedzi na to pytanie.
Po pierwsze chcę ustawić coś prostego dla wszystkich przyszłych czytelników ... Wartości NULL reprezentują nieznane dane, NIE NIE wykorzystane dane. Jeśli masz tabelę pracowników z polem daty rozwiązania umowy. Wartość zerowa w dacie zakończenia wynika z tego, że jest to pole wymagane w przyszłości, które jest obecnie nieznane. Każdy pracownik, niezależnie od tego, czy jest aktywny czy zwalniany, w pewnym momencie będzie miał datę dodaną do tego pola. To jest moim zdaniem jedyny powód, dla którego pole Nullable.
Biorąc to pod uwagę, ta sama tabela pracowników najprawdopodobniej zawiera dane uwierzytelniające. W środowisku korporacyjnym pracownicy są umieszczani w bazie danych dla działu kadr i księgowości, ale nie zawsze mają lub nie potrzebują szczegółów uwierzytelnienia. Większość odpowiedzi prowadzi do przekonania, że nieważne jest zerowanie tych pól lub w niektórych przypadkach utworzenie dla nich konta, ale nigdy nie wysyłanie im poświadczeń. Pierwszy z nich spowoduje, że Twój zespół programistów napisze kod, aby sprawdzić wartości NULL i odpowiednio sobie z nimi poradzić, a drugi stanowi ogromne zagrożenie bezpieczeństwa! Konta, które nigdy nie są jeszcze używane w systemie, zwiększają tylko liczbę możliwych punktów dostępu dla hakerów, a ponadto zajmują cenne miejsce w bazie danych dla czegoś, co nigdy nie jest używane.
Biorąc pod uwagę powyższe informacje, najlepszym sposobem na radzenie sobie z zerowalnymi danymi, które BĘDĄ być używane, jest dopuszczenie wartości zerowalnych. To smutne, ale prawdziwe, a twoi programiści będą cię za to nienawidzić. Drugi typ zerowalnych danych należy umieścić w powiązanej tabeli (IE: Konto, poświadczenia itp.) I mieć relację jeden do jednego. Umożliwia to istnienie użytkownika bez poświadczeń, chyba że są one potrzebne. Eliminuje to dodatkowe ryzyko bezpieczeństwa, cenne miejsce w bazie danych i zapewnia znacznie czystszą bazę danych.
Poniżej znajduje się bardzo uproszczona struktura tabeli pokazująca zarówno wymaganą zerowalną kolumnę, jak i relację jeden do jednego.
Wiem, że jestem trochę spóźniony na imprezę od czasu, gdy zadano to pytanie lata temu, ale mam nadzieję, że pomoże to rzucić nieco światła na tę kwestię i jak najlepiej sobie z tym poradzić.
źródło
TerminationDate
w aktach pracownika, ale mieć tabelę, doTerminatedEmployee
której pracownicy są przenoszeni (nie kopiowani) przez aplikację po ich rozwiązaniu. Oczywiście działa to dobrze z tabelą Konta, ponieważ nie będzie połączonego konta wTerminatedEmployee
tabeli. Jeśli nadal potrzebujesz numerów telefonów, odwróciłbym klucze obce, aby pracownik i wypisane tabele pracowników miały identyfikator numeru telefonu zamiast na odwrót.Oprócz wszystkich problemów z mylącymi programistami NULL, NULL mają jeszcze jedną bardzo poważną wadę: wydajność
Kolumny NULL są katastrofą z punktu widzenia wydajności. Rozważmy arytmetykę liczb całkowitych jako przykład. W zdrowym świecie bez wartości NULL można łatwo wektoryzować arytmetykę liczb całkowitych w kodzie silnika bazy danych za pomocą instrukcji SIMD, aby wykonać prawie dowolne obliczenia przy prędkościach większych niż 1 wiersz na cykl procesora. Jednak w chwili wprowadzenia wartości NULL musisz zająć się wszystkimi specjalnymi przypadkami, które tworzy NULL. Nowoczesne zestawy instrukcji procesora (czytaj także: x86 / x64 / ARM i logika GPU) po prostu nie są przygotowane do tego, aby to zrobić skutecznie.
Rozważ podział jako przykład. Na bardzo wysokim poziomie jest to logika, której potrzebujesz z liczbą całkowitą inną niż null:
Z NULL staje się to nieco trudniejsze. Razem z
b
tobą potrzebujesz wskaźnika, jeślib
jest zerowy i podobnie dlaa
. Czek staje się teraz:Arytmetyka NULL działa znacznie wolniej na nowoczesnym procesorze niż arytmetyka nie zerowa (około 2-3 razy).
Gorzej, gdy wprowadzisz SIMD. Dzięki SIMD nowoczesny procesor Intel może wykonywać 4 x 32-bitowe podziały liczb całkowitych w jednej instrukcji, jak to:
Istnieją również sposoby radzenia sobie z wartością NULL w SIMD, ale wymaga to użycia większej liczby wektorów i rejestrów procesora oraz sprytnego maskowania bitów. Nawet przy dobrych sztuczkach, spadek wydajności arytmetyki liczb całkowitych NULL wkracza do 5-10x wolniejszego zakresu, nawet dla stosunkowo prostych wyrażeń.
Coś podobnego do powyższego dotyczy agregatów i do pewnego stopnia również złączeń.
Innymi słowy: Istnienie NULL w SQL jest niedopasowaniem impedancji między teorią baz danych a rzeczywistym projektowaniem współczesnych komputerów. Jest całkiem dobry powód, dla którego NULL myli deweloperów - ponieważ liczba całkowita nie może być NULL w większości rozsądnych języków programowania - po prostu nie tak działają komputery.
źródło
Ciekawe pytania
To jest bardziej skomplikowane. Null ma wiele wyraźnych znaczeń, a jednym naprawdę ważnym powodem, aby nie dopuszczać wartości null w wielu kolumnach jest to, że gdy kolumna ma wartość null, oznacza to jedną i tylko jedną rzecz (mianowicie to, że nie pojawiła się w złączeniu zewnętrznym). Dodatkowo pozwala ustalić minimalne standardy wprowadzania danych, co jest naprawdę pomocne.
To od razu ilustruje problem z zerami, mianowicie, że wartość przechowywana w tabeli może oznaczać „ta wartość nie ma zastosowania” lub „nie wiemy”. W przypadku ciągów pusty ciąg może służyć jako „nie dotyczy”, ale w przypadku dat i godzin nie ma takiej konwencji, ponieważ nie ma prawidłowej wartości, co konwencjonalnie to oznacza. Zazwyczaj utkniesz przy użyciu wartości NULL.
Istnieją sposoby na obejście tego (poprzez dodanie większej liczby relacji i łączenie), ale stwarzają one dokładnie takie same problemy z klarownością semantyczną, jakie mają wartości NULL w bazie danych. W przypadku tych baz danych nie martwiłbym się tym. Po prostu tak naprawdę nic na to nie poradzisz.
EDYCJA: Jednym z obszarów, w których wartości NULL są niezbędne, są klucze obce. Tutaj zazwyczaj mają tylko jedno znaczenie, identyczne z null w zewnętrznym znaczeniu łączenia. Jest to oczywiście wyjątek od problemu.
źródło
Artykuł Wikipedii na temat SQL Null zawiera kilka interesujących uwag na temat wartości NULL, a jako odpowiedź niezależna od bazy danych, o ile masz świadomość potencjalnego wpływu posiadania wartości NULL dla określonego RDBMS, są one dopuszczalne w twoim projekcie. Gdyby tak nie było, nie można określić kolumn jako zerowalnych.
Pamiętaj tylko o tym, w jaki sposób RDBMS obsługuje je w operacjach SELECT, takich jak matematyka, a także w indeksach.
źródło
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:
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.
źródło