it-swarm-eu.dev

Proč bychom neměli povolit NULL?

Pamatuji si přečtení tohoto jednoho článku o návrhu databáze a také si pamatuji, že jsem řekl, že byste měli mít vlastnosti pole NE NULL. Nepamatuji si, proč tomu tak bylo.

Zdá se mi, že si myslím, že jako vývojář aplikací nemusíte testovat na NULL a možnou neexistující datovou hodnotu (například prázdný řetězec pro řetězce).

Co ale děláte v případě dat, datetime a času (SQL Server 2008)? Budete muset použít nějaké historické nebo zdola-datum.

Máte na to nějaké nápady?

127
Thomas Stringer

Myslím, že otázka je špatně formulovaná, protože formulace naznačuje, že už jste se rozhodli, že NULL jsou špatní. Možná jste mysleli "Měli bychom povolit NULL?"

Každopádně, tady je můj názor: Myslím, že NULL jsou dobrá věc. Když začnete zabraňovat NULL jen proto, že „NULL jsou špatné“ nebo „NULL jsou těžké“, začnete vytvářet data. Co když například neznáte moje datum narození? Co hodláte dát do sloupce, dokud to nevíte? Pokud jste něco jako spousta anti-NULL lidí, vstoupíte do 1900-01-01. Teď se umístím na geriatrické oddělení a pravděpodobně mi zavolá místní zpravodajská stanice, která mi blahopřeje k mému dlouhému životu, požádala mě o svá tajemství, abych žila tak dlouhý život atd.

Pokud lze zadat řádek, kde je možné, že nevíte hodnotu sloupce, I myslím, že NULL dává mnohem větší smysl než vybírání nějaké libovolné hodnoty tokenu, která představuje skutečnost, že není známa - hodnota, kterou ostatní budou muset znát, obrátit se na ni nebo se zeptat, aby zjistili, co to znamená.

Existuje však rovnováha - ne každý sloupec ve vašem datovém modelu by měl být nulovatelný. Ve formuláři jsou často volitelná pole nebo informace, které se v době vytvoření řádku jinak neshromažďují. Ale to neznamená, že můžete odložit vyplnění všech dat. :-)

Také schopnost používat NULL může být omezena zásadními požadavky v reálném životě. Například v oblasti medicíny může být věcí života nebo smrti vědět , proč hodnota není známa. Je srdeční frekvence NULL, protože tam nebyl puls, nebo protože jsme to ještě neměřili? V takovém případě můžeme vložit NULL do sloupce srdeční frekvence a mít poznámky nebo jiný sloupec s NULL, protože důvod?

Nebojte se NULL, ale buďte ochotni se učit nebo diktovat, kdy a kde by měli být použity a kdy a kde by neměli.

232
Aaron Bertrand

Zjištěné důvody jsou:

  • NULL není hodnota, a proto nemá žádný vlastní datový typ. Null potřebují speciální zacházení všude , když kód, který se jinak spoléhá na skutečné typy, může také obdržet nenapsaný NULL.

  • NULL přeruší logiku dvou hodnot (známá pravda nebo nepravda) a vyžaduje logiku tří hodnot. To je mnohem složitější, aby se správně implementovalo, a většina DBA a nepochopitelné je to nepochopitelně. V důsledku toho pozitivně zve v aplikaci mnoho jemných chyb .

  • sémantický význam jakékoli konkrétní NULL je ponechán na aplikaci , na rozdíl od skutečných hodnot.

    Sémantika jako „nepoužije se“ a „neznámá“ a „sentinelová“ je běžná a existují i ​​další. Často se používají současně ve stejné databázi, dokonce ve stejném vztahu; a jsou samozřejmě nevysvětlitelné a nerozeznatelné a nekompatibilní významy.

  • nejsou nutné pro relační databáze , jak je uvedeno v „Jak zacházet s chybějícími informacemi bez nulových hodnot“ . Další normalizace je zjevným prvním krokem k pokusu o zbavení tabulky NULL.

To neznamená, že by NULL nemělo být nikdy povoleno. argumentuje , že existuje mnoho dobrých důvodů, proč zakázat NULL, kdykoli je to možné.

Významné je, že se snaží velmi tvrdě - prostřednictvím lepšího návrhu schématu a lepších databázových strojů a ještě lepších databázových jazyků - , aby bylo možné vyhnout se NULL častěji.

Fabian Pascal odpovídá na řadu argumentů v „Nulls Nullified“ .

61
bignose

Nesouhlasím, nuly jsou základním prvkem návrhu databáze. Alternativou, jak jste také zmínil, by bylo rozšíření známých hodnot, které představují chybějící nebo neznámé. Problém spočívá v tom, že null je tak široce nepochopený a v důsledku toho je používán nevhodně.

IIRC, Codd navrhl, aby současná implementace nulové hodnoty (tzn. Neexistující/chybějící) mohla být vylepšena tím, že budou mít dva nulové markery namísto jednoho, „není přítomen, ale použitelný“ a „není přítomen a není použitelný“. Nedokážu si představit, jak by to osobně vylepšilo relační návrhy.

32

Dovolte mi začít tím, že řeknu, že nejsem DBA, jsem vývojářem ze srdce a udržuji a aktualizuji naše databáze na základě našich potřeb. Vzhledem k tomu jsem měl stejnou otázku z několika důvodů.

  1. Nulové hodnoty ztěžují vývoj a jsou náchylné k chybám.
  2. Nulové hodnoty zvyšují složitost dotazů, uložených procedur a pohledů a náchylné k chybám.
  3. Nulové hodnoty zabírají místo (? Bajty na základě pevné délky sloupce nebo 2 bajty na proměnnou délku sloupce).
  4. Nulové hodnoty mohou a často ovlivňují indexování a matematiku.

Strávil jsem velmi dlouhou dobu prosíváním spoustou odpovědí, komentářů, článků a rad po celém internetu. Není třeba říkat, že většina informací byla stejná jako odpověď @ AaronBertranda. Proto jsem cítil potřebu odpovědět na tuto otázku.

Nejprve chci nastavit něco pro všechny budoucí čtenáře ... NULL hodnoty představují neznámá data NEPOUŽÍVANÁ data. Pokud máte tabulku zaměstnanců s polem datum ukončení. Nulová hodnota v datu ukončení je proto, že se jedná o budoucí povinné pole, které je momentálně neznámé. Každý zaměstnanec, ať už je aktivní nebo ukončený, bude v určitém okamžiku do tohoto pole přidán datum. To je podle mého názoru jediný a jediný důvod pro pole Nullable.

Jak již bylo řečeno, stejná tabulka zaměstnanců by s největší pravděpodobností obsahovala nějaký druh ověřovacích údajů. V podnikovém prostředí je běžné, že zaměstnanci budou v databázi uvedeni pro HR a účetnictví, ale ne vždy mají nebo nepotřebují podrobnosti o autentizaci. Většina odpovědí by vás vedla k domněnce, že je v pořádku tato pole zrušit, nebo v některých případech pro ně vytvořit účet, ale nikdy jim neodeslat přihlašovací údaje. První způsobí, že váš vývojový tým napíše kód, který zkontroluje NULL, a podle toho se s nimi vypořádá, a ten představuje velké bezpečnostní riziko! Účty, které se v systému dosud nepoužívají, pouze zvyšují počet možných přístupových bodů pro hackera a navíc zabírají cenný databázový prostor pro něco, co se nikdy nepoužívá.

Vzhledem k výše uvedeným informacím je nejlepším způsobem, jak zacházet s nulovatelnými daty, která budou použita, povolit nulovatelné hodnoty. Je to smutné, ale pravdivé a vaši vývojáři vás za to nenávidí. Druhý typ nulovatelných dat by měl být vložen do související tabulky (IE: Account, Credentials atd.) A měl by mít vzájemný vztah. To umožňuje uživateli existovat bez přihlašovacích údajů, pokud nejsou potřeba. Tím se odstraní další bezpečnostní riziko, cenný databázový prostor a poskytne se mnohem čistší databáze.

Níže je uvedena velmi zjednodušená struktura tabulky, která ukazuje jak požadovaný nulovatelný sloupec, tak vztah mezi dvěma.

Unknown Nullable and One-to-One relationship

Vím, že jsem na stranu trochu pozdě, protože tato otázka byla položena před lety, ale doufejme, že to pomůže objasnit tuto otázku a jak nejlépe ji řešit.

14
Nicholas Aguirre

Kromě všech problémů s NULL matoucími vývojáři mají NULL další velmi vážnou nevýhodu: Výkon

NULL'able sloupce jsou katastrofou z hlediska výkonu. Jako příklad zvažte celou aritmetiku. Ve zdravém světě bez NULL je „snadné“ vektorizovat celočíselnou aritmetiku v kódu databázového stroje pomocí instrukcí SIMD k provádění téměř jakéhokoli výpočtu rychlostí rychleji než 1 řádek na cyklus CPU. Ve chvíli, kdy představíte NULL, však budete muset zpracovat všechny speciální případy, které NULL vytvoří. Moderní instrukční sady CPU (číst také: x86/x64/ARM a logika GPU) jednoduše nejsou vybaveny k tomu, aby to dokázaly efektivně.

Jako příklad zvažte rozdělení. Na velmi vysoké úrovni je to logika, kterou potřebujete s nenulovým celkovým číslem:

if (b == 0)
  do something when dividing by error
else
  return a / b

U NULL se to stává trochu složitější. Spolu s b budete potřebovat indikátor, pokud b je null a podobně pro a. Kontrola se nyní stává:

if (b_null_bit == NULL)
   return NULL
else if (b == 0) 
   do something when dividing by error
else if (a_null_bit == NULL)
   return NULL
else 
   return a / b

Aritmetika NULL je výrazně pomalejší při běhu na moderním procesoru než null aritmetika (faktorem přibližně 2 - 3 x).

Zhorší se, když představíte SIMD. Se SIMD může moderní procesor Intel provádět 4 x 32bitové celočíselné dělení v jedné instrukci, jako například:

x_vector = a_vector / b_vector
if (fetestexception(FE_DIVBYZERO))
   do something when dividing by zero
return x_vector;

Nyní existují způsoby, jak zacházet s NULL v SIMD land, ale to vyžaduje použití více vektorů a CPU registrů a provedení nějakého chytrého maskování bitů. Dokonce i při dobrých trikech se výkonnostní pokuta celočíselné aritmetické hodnoty NULL vplíží do pomalejšího rozsahu 5-10x, a to i pro relativně jednoduché výrazy.

Něco jako výše platí pro agregáty a do jisté míry i pro spojení.

Jinými slovy: Existence NULL v SQL je impedančním nesouladem mezi teorií databáze a skutečným designem moderních počítačů. Existuje docela dobrý důvod, proč NULL zaměňuje vývojáře - protože celé číslo nemůže být ve většině zdravých programovacích jazycích NULL - prostě to není způsob, jak počítače fungují.

13
Thomas Kejser

Článek Wikipedie o SQL Null obsahuje několik zajímavých poznámek o hodnotě NULL a jako odpověď na databázi agnostická, pokud jste si vědomi možných dopadů, které mají hodnoty NULL pro váš konkrétní RDBMS, jsou přijatelný ve vašem designu. Pokud by tomu tak nebylo, nebylo by možné určit sloupce jako neplatné.

Jen si uvědomte, jak s nimi RDBMS pracuje v operacích SELECT, jako je matematika, a také v indexech.

10
Derek Downey

Zajímavé otázky.

Zdá se mi, že si myslím, že jako vývojář aplikací nemusíte testovat NULL a možnou neexistující hodnotu dat (například prázdný řetězec pro řetězce).

Je to složitější než to. Null má řadu odlišných významů a jedním opravdu důležitým důvodem, proč nepovolovat null v mnoha sloupcích, je to, že když je sloupec null, pak to znamená jednu a pouze jednu věc (jmenovitě to, že se neobjevilo ve vnějším spojení). Navíc vám umožňuje nastavit minimální standardy pro zadávání dat, což je skutečně užitečné.

Co ale děláte v případě dat, datetime a času (SQL Server 2008)? Budete muset použít nějaké historické nebo zdola-datum.

To ilustruje problém s nulovými hodnotami hned, a to, že hodnota uložená v tabulce může znamenat buď „tato hodnota se nevztahuje“, nebo „nevíme“. U řetězců může prázdný řetězec sloužit jako „to neplatí“, ale s daty a časy neexistuje taková konvence, protože neexistuje žádná platná hodnota, která to běžně znamená. Obvykle tam uvíznete pomocí NULL.

Existují způsoby, jak se tomu obejít (přidáním více vztahů a spojením), ale ty představují přesně stejné problémy sémantické čistoty, jaké mají NULL v databázi. U těchto databází bych se tím nebál. Na tom prostě není nic, co byste s tím mohli dělat.

ÚPRAVA: Jedna oblast, kde NULLs are nepostradatelné, je v cizích klíčích. Zde mají obvykle pouze jeden význam, identický s nulovým ve vnějším spojení. Toto je samozřejmě výjimka z problému.

10
Chris Travers