Mengapa kita tidak mengizinkan NULL?

125

Saya ingat membaca artikel yang satu ini tentang desain database dan saya juga ingat dikatakan bahwa Anda harus memiliki properti field NOT NULL. Saya tidak ingat mengapa ini terjadi.

Yang bisa saya pikirkan hanyalah bahwa, sebagai pengembang aplikasi, Anda tidak perlu menguji NULL dan kemungkinan nilai data yang tidak ada (misalnya, string kosong untuk string).

Tapi apa yang Anda lakukan dalam hal tanggal, waktu, dan waktu (SQL Server 2008)? Anda harus menggunakan tanggal yang bersejarah atau bottom-up.

Ada ide tentang ini?

Thomas Stringer
sumber
4
Jawaban ini memiliki wawasan tentang penggunaan NULL dba.stackexchange.com/questions/5176/…
Derek Downey
10
Benarkah? Mengapa RDBMS memungkinkan kami untuk menggunakan NULL sama sekali, jika kami tidak menggunakannya? Tidak ada yang salah dengan NULL selama Anda tahu cara menghadapinya.
Fr0zenFyr
3
Apakah ini pemodelan data BI? Anda seharusnya tidak mengizinkan null dalam tabel fakta ... jika tidak, null adalah teman Anda jika digunakan dengan benar. =)
sam yi
2
@ Fr0zenFyr, hanya karena RDBMS memungkinkan kita melakukan sesuatu, itu belum tentu ide yang baik untuk melakukannya. Tidak ada yang memaksa kami untuk mendeklarasikan kunci utama atau kunci unik dalam sebuah tabel, tetapi dengan beberapa pengecualian kami melakukannya.
Lennart
3
Saya pikir perawatan lengkap dari subjek ini harus membuat referensi ke persyaratan asli Codd bahwa RDBMS harus memiliki cara sistematis untuk memperlakukan data yang hilang. Di dunia nyata, ada situasi di mana lokasi untuk data dibuat, tetapi tidak ada data untuk dimasukkan ke dalamnya. Arsitek Data harus memberikan respons terhadap hal ini, apakah itu melibatkan desain basis data, pemrograman aplikasi, atau keduanya. SQL NULL kurang sempurna dalam memenuhi persyaratan ini, tetapi lebih baik daripada tidak sama sekali.
Walter Mitty

Jawaban:

230

Saya pikir pertanyaannya tidak tepat, karena kata-kata itu menyiratkan bahwa Anda telah memutuskan bahwa NULL itu buruk. Mungkin maksudmu, "Haruskah kita mengizinkan NULL?"

Bagaimanapun, ini adalah pendapat saya: Saya pikir NULL adalah hal yang baik. Ketika Anda mulai mencegah NULL hanya karena "NULLs buruk" atau "NULLs sulit", Anda mulai membuat data. Misalnya, bagaimana jika Anda tidak tahu tanggal lahir saya? Apa yang akan Anda taruh di kolom sampai Anda tahu? Jika Anda seperti banyak orang anti-NULL, Anda akan memasukkan 1900-01-01. Sekarang saya akan ditempatkan di bangsal geriatri dan mungkin mendapat telepon dari stasiun berita lokal saya memberi selamat kepada saya atas umur panjang saya, meminta saya rahasiaku untuk menjalani umur panjang, dll.

Jika sebuah baris dapat dimasukkan di mana dimungkinkan bahwa Anda tidak tahu nilai kolom, saya pikir NULL lebih masuk akal daripada memilih beberapa nilai token sewenang-wenang untuk mewakili fakta bahwa tidak diketahui - nilai yang orang lain akan harus sudah tahu, merekayasa balik, atau bertanya-tanya untuk mencari tahu apa artinya.

Ada keseimbangan, meskipun - tidak setiap kolom dalam model data Anda harus nullable. Sering ada bidang opsional pada formulir, atau potongan informasi yang jika tidak dikumpulkan pada saat baris dibuat. Tetapi itu tidak berarti Anda dapat menunda mengisi semua data. :-)

Juga kemampuan untuk menggunakan NULL dapat dibatasi oleh persyaratan penting dalam kehidupan nyata. Di bidang medis, misalnya, bisa menjadi masalah hidup atau mati untuk mengetahui mengapa suatu nilai tidak diketahui. Apakah detak jantung NULL karena tidak ada denyut nadi, atau karena kita belum mengukurnya? Dalam kasus seperti itu, dapatkah kita meletakkan NULL di kolom detak jantung, dan memiliki catatan atau kolom berbeda dengan alasan NULL-karena?

Jangan takut pada NULLs, tetapi berkeinginan untuk belajar atau menentukan kapan dan di mana mereka harus digunakan, dan kapan dan di mana mereka seharusnya tidak.

Aaron Bertrand
sumber
3
"beberapa nilai token sewenang-wenang untuk mewakili fakta bahwa itu tidak diketahui" ini dikenal sebagai nilai sentinel
Alexander
4
Tapi apa yang mencegah Anda membuat tabel terpisah birth_datetempat Anda menyimpan tanggal lahir? Jika tanggal lahir tidak diketahui maka jangan masukkan tanggal lahir birth_date. Null adalah bencana.
Eldar Agalarov
6
@EldarAgalarov Kedengarannya seperti alasan Trump ("bencana" mengapa? Bagaimana? Untuk siapa? Pendapat Anda bahwa ada sesuatu yang merupakan "bencana" tidak membuatnya demikian). Pokoknya tanggal lahir hanyalah salah satu contoh. Jika Anda memiliki personel atau anggota atau pelanggan yang memiliki 15 kolom yang berpotensi dapat dibatalkan, apakah Anda akan membuat 15 tabel sekunder? Bagaimana jika Anda memiliki 50? Bagaimana jika tabel fakta DW Anda memiliki 500? Mempertahankan agar NULL menakutkan yang sangat besar dari database Anda menjadi 10x sama buruknya dengan “bencana” yang Anda takuti ...
Aaron Bertrand
3
@ AaronBertrand jika meja Anda memiliki 15 kolom yang berpotensi dapat dibatalkan, baunya sangat buruk ^^ Bukan berarti sejumlah besar kolom secara inheren buruk, tetapi mungkin menunjukkan desain yang buruk ATAU denasionalisasi yang diperlukan. Tapi itu akan menimbulkan pertanyaan.
programath
2
@ Kartu Memori Jadi Anda belum pernah melihat orang menyimpan 1900-01-01untuk menghindari nilai tanggal / waktu NULL? Baiklah kalau begitu. Juga, NULL = tidak diketahui dan tidak diketahui = salah. Saya tidak yakin masalah apa yang mungkin menyebabkan hal ini selain orang tidak dilahirkan dengan mengetahui hal itu (seperti mereka tidak dilahirkan dengan mengetahui banyak hal yang melekat dalam RDBMS yang kompleks). Sekali lagi, melambaikan tangan dan berkata "Masalah! Bencana!" tidak membuatnya begitu.
Aaron Bertrand
57

Alasan yang ditetapkan adalah:

  • NULL bukan nilai, dan karenanya tidak memiliki tipe data intrinsik. Nulls memerlukan penanganan khusus di semua tempat ketika kode yang bergantung pada tipe aktual juga dapat menerima NULL yang tidak diketik.

  • NULL memecah logika dua-nilai (familiar Benar atau Salah), dan membutuhkan logika tiga-nilai. Ini jauh lebih kompleks untuk diimplementasikan dengan benar, dan tentu saja kurang dipahami oleh sebagian besar DBA dan hampir semua non-DBA. Sebagai akibatnya, itu mengundang banyak bug halus dalam aplikasi.

  • The makna semantik dari setiap NULL tertentu yang tersisa untuk aplikasi , tidak seperti nilai yang sebenarnya.

    Semantik seperti “tidak berlaku” dan “tidak dikenal” dan “penjaga” adalah umum, dan ada juga yang lain. Mereka sering digunakan secara bersamaan dalam database yang sama, bahkan dalam hubungan yang sama; dan tentu saja makna yang tidak jelas dan tidak bisa dibedakan serta tidak sesuai .

  • Mereka tidak perlu ke database relasional , seperti yang diperdebatkan dalam "Cara Menangani Informasi yang Hilang Tanpa Nulls" . Normalisasi lebih lanjut adalah langkah pertama yang jelas untuk mencoba membersihkan tabel NULL.

Ini tidak berarti NULL tidak boleh diizinkan. Ini tidak berpendapat bahwa ada banyak alasan yang baik untuk melarang NULL jika memungkinkan.

Secara signifikan, ini berpendapat untuk berusaha sangat keras - melalui desain skema yang lebih baik, dan mesin database yang lebih baik, dan bahasa database yang lebih baik - untuk membuatnya layak untuk menghindari NULL lebih sering.

Fabian Pascal menanggapi sejumlah argumen, dalam “Nulls Nullified” .

hidung besar
sumber
3
Tautan Anda ke "Cara Menangani Informasi yang Hilang Tanpa Nulls" menunjukkan dengan sangat baik mengapa kami tidak dapat melakukannya tanpa nol: Beberapa saran tidak mungkin diterapkan dengan cara yang rasional pada RDBMS utama seperti saat ini.
Jack Douglas
7
Jack: Benar, tapi "implementasi saat ini tidak bisa melakukannya" bukan argumen untuk status quo :-)
bignose
17
Apakah seperti itu mengatakan kita tidak boleh terbang karena pesawat tidak sempurna?
Aaron Bertrand
11
Tidak, itu mengatakan bahwa vendor harus berhenti meminta alasan untuk null yang mungkin telah valid empat puluh tahun yang lalu, tetapi telah lama melewati periode penyimpanan yang masuk akal. Waktu I / O tidak lagi dalam urutan besarnya 80 ms. Siklus CPU tunggal tidak lagi dalam urutan besaran mikrodetik. Batas memori tidak lagi dalam urutan besarnya beberapa Meg. Tidak seperti empat puluh tahun yang lalu, kecepatan dan kapasitas perangkat keras yang diperlukan untuk bekerja tanpa nulls sekarang ada dengan biaya yang tidak menghalangi. Dia mengatakan sudah waktunya untuk pindah.
Erwin Smout
2
Tautan "NULL kebingungan" sudah mati.
jpmc26
32

Saya tidak setuju, nulls adalah elemen penting dari desain database. Alternatifnya, seperti yang Anda singgung juga, akan menjadi proliferasi nilai-nilai yang diketahui untuk mewakili yang hilang atau tidak diketahui. Masalahnya terletak pada nol yang begitu banyak disalahpahami dan akibatnya digunakan secara tidak tepat.

IIRC, Codd menyarankan implementasi null saat ini (artinya tidak ada / hilang) dapat ditingkatkan dengan memiliki dua marker nol daripada satu, "tidak ada tetapi dapat diterapkan" dan "tidak ada dan tidak dapat diterapkan". Tidak dapat membayangkan bagaimana desain relasional ditingkatkan oleh ini secara pribadi.

Mark Storey-Smith
sumber
2
Saya sarankan memiliki satu set yang ditentukan pengguna dari berbagai jenis null, dan logika multi-nilai yang ditetapkan pengguna untuk pergi bersama mereka: p
Jack Douglas
13
Itu bukan satu-satunya pilihan. Anda mengecualikan alternatif normalisasi: Alih-alih kolom yang mungkin atau mungkin tidak memiliki nilai, gunakan tabel lain yang mungkin atau mungkin tidak memiliki baris yang sesuai untuk tabel pertama. Arti ada atau tidaknya suatu baris disyaratkan dalam arti tabel, dan tidak ada casing khusus dari nilai NULL atau nilai sentinel dll.
bignose
7
Kehadiran NULL tidak membutuhkan nilai casing khusus atau sentinel. Itu hanya gejala bagaimana beberapa orang memutuskan untuk berurusan dengan NULL.
Aaron Bertrand
Perlu dicatat bahwa '' berbeda dari nol pada PostgreSQL (meskipun bukan Oracle) dan memberi Anda penanda dua kali lipat, dan Anda dapat menggunakan 0 untuk kolom angka. Masalahnya dengan 0 adalah tidak bekerja untuk kunci asing.
Chris Travers
13

Biarkan saya memulai dengan mengatakan saya bukan seorang DBA, saya seorang pengembang pada dasarnya dan saya memelihara dan memperbarui basis data kami berdasarkan kebutuhan kami. Yang sedang berkata, saya punya pertanyaan yang sama karena beberapa alasan.

  1. Nilai kosong membuat pengembangan lebih sulit dan rawan bug.
  2. Nilai kosong membuat kueri, prosedur tersimpan, dan tampilan lebih kompleks dan rawan bug.
  3. Nilai kosong mengambil ruang (? Byte berdasarkan panjang kolom tetap atau 2 byte untuk panjang kolom variabel).
  4. Nilai kosong dapat dan sering mempengaruhi pengindeksan dan matematika.

Saya menghabiskan waktu yang sangat lama memilah-milah banyak tanggapan, komentar, artikel, dan saran di seluruh internet. Tidak perlu dikatakan bahwa sebagian besar informasinya hampir sama dengan respons @ AaronBertrand. Itulah sebabnya saya merasa perlu untuk menanggapi pertanyaan ini.

Pertama saya ingin meluruskan sesuatu untuk semua pembaca masa depan ... Nilai NULL mewakili data yang tidak diketahui BUKAN data yang tidak digunakan. Jika Anda memiliki tabel karyawan yang memiliki bidang tanggal pemutusan hubungan kerja. Nilai nol pada tanggal terminasi adalah karena ini merupakan bidang wajib di masa depan yang saat ini tidak diketahui. Setiap karyawan baik itu aktif atau diberhentikan pada suatu saat akan memiliki tanggal yang ditambahkan ke bidang itu. Itu menurut saya satu-satunya alasan untuk bidang Nullable.

Yang sedang berkata tabel karyawan yang sama kemungkinan besar akan menyimpan beberapa jenis data otentikasi. Merupakan hal yang umum dalam lingkungan perusahaan bahwa karyawan akan terdaftar dalam database untuk HR dan akuntansi tetapi tidak selalu memiliki atau memerlukan detail otentikasi. Sebagian besar tanggapan akan membuat Anda percaya bahwa tidak masalah untuk membatalkan bidang tersebut atau dalam beberapa kasus membuat akun untuk mereka tetapi tidak pernah mengirimi mereka kredensial. Yang pertama akan menyebabkan tim pengembangan Anda untuk menulis kode untuk memeriksa NULL dan untuk menghadapinya sesuai dan yang terakhir menimbulkan risiko keamanan besar! Akun yang belum pernah digunakan dalam sistem hanya meningkatkan jumlah titik akses yang mungkin bagi seorang peretas, ditambah lagi mereka mengambil ruang basis data yang berharga untuk sesuatu yang tidak pernah digunakan.

Mengingat informasi di atas, cara terbaik untuk menangani data nullable yang AKAN digunakan adalah untuk memungkinkan nilai-nilai nullable. Ini menyedihkan tetapi benar dan pengembang Anda akan membenci Anda karenanya. Tipe kedua data yang dapat dibatalkan harus diletakkan dalam tabel terkait (IE: Akun, Kredensial, dll) dan memiliki hubungan Satu-ke-Satu. Ini memungkinkan pengguna ada tanpa kredensial kecuali diperlukan. Ini menghilangkan risiko keamanan ekstra, ruang basis data yang berharga, dan menyediakan basis data yang jauh lebih bersih.

Di bawah ini adalah struktur tabel yang sangat sederhana yang menunjukkan kolom nullable yang diperlukan dan hubungan Satu-ke-Satu.

Hubungan Nullable dan One-to-One Tidak Diketahui

Saya tahu saya sedikit terlambat ke pesta karena pertanyaan ini diajukan bertahun-tahun yang lalu, tetapi mudah-mudahan ini akan membantu untuk menjelaskan masalah ini dan cara terbaik untuk mengatasinya.

Nicholas Aguirre
sumber
2
Saya hanya akan mengubahnya sehingga tidak ada TerminationDatedalam catatan karyawan, tetapi memiliki tabel di TerminatedEmployeemana karyawan dipindahkan ke (tidak disalin) oleh aplikasi ketika mereka diberhentikan. Jelas ini berfungsi baik dengan tabel Akun karena tidak akan ada akun tertaut di atas TerminatedEmployeemeja. Jika Anda masih memerlukan nomor telepon, saya akan membalikkan kunci asing sehingga tabel karyawan dan karyawan yang diputus memiliki id nomor telepon alih-alih sebaliknya.
Programster
2
Saya benar-benar dapat melanjutkan selama berhari-hari tentang mengapa ini akan menjadi buruk. Tabel redundan, praktik SQL yang buruk, sehingga pengembang Anda harus mencari di dua tempat untuk data karyawan, masalah dengan pelaporan, masalah dengan URI langsung ke karyawan yang tidak ada (telah dipindahkan), dan daftar berjalan terus dan terus. Benar-benar baik-baik saja untuk memiliki NULLS untuk bidang yang suatu hari nanti akan memiliki nilai, itu cerita lain untuk memiliki bidang yang tidak pernah diisi dan tidak pernah digunakan. Sejumlah masalah dan penyelesaian potensial untuk membuat pekerjaan ini tidak sebanding dengan masalah kecil untuk memeriksa NULL di bidang.
Nicholas Aguirre
1
Saya tidak setuju. Satu-satunya hal yang redundan adalah bidang nol untuk tanggal penghentian yang mungkin tidak pernah diisi. Pengembang hanya perlu melihat tabel yang sesuai untuk data yang mereka inginkan, dan dapat meningkatkan kinerja. Jika karena alasan tertentu, Anda ingin karyawan yang diberhentikan dan tidak diberhentikan, diselesaikan dengan bergabung, tetapi 90% dari waktu aplikasi Anda mungkin ingin satu atau yang lain. Saya pikir tata letak yang saya tentukan lebih baik karena tidak mungkin untuk memiliki tanggal pemutusan hubungan kerja pada seorang karyawan dan baginya masih memiliki akun.
Programster
2
Saya tidak mengatakan data yang berlebihan, saya mengatakan tabel yang berlebihan. Plus, setiap perubahan pada tabel karyawan harus mengalir ke tabel yang diakhiri; ini membuat aplikasi rawan kesalahan dan itu membuat pekerjaan pengembang jauh lebih sulit. Plus, bidang tanggal Pengakhiran akan diisi untuk hampir semua orang. Itu boros dan bermasalah untuk membuat struktur tabel identik kedua dan juga memindahkan data. Tidak termasuk pengujian setiap kali untuk memastikan data tabel dipindahkan dan dibersihkan. Ini adalah praktik buruk untuk menghapus data dari tabel, meskipun hanya memindahkannya. Jika Anda begitu peduli dengan satu bidang yang ...
Nicholas Aguirre
1
... yang hampir selalu diisi dalam waktu kemudian membuat tabel terminasi dengan hubungan 1to1 kembali ke karyawan. Saya bekerja dengan berbagai database sepanjang hari baik sebagai DBA dan sebagai pengembang dan saya senang saya belum menemukan satu dengan struktur yang Anda usulkan. Terutama dari sudut pandang pengembang, itu akan menjadi mimpi buruk untuk menulis dan memeriksa kesalahan semuanya karena Anda tidak akan tahu dari mana tabel itu berasal. Bahkan menulis gabungan, data yang dikembalikan ke perangkat lunak akan memiliki bidang dengan data nol yang masih akan mengharuskan Anda untuk mengujinya juga.
Nicholas Aguirre
13

Terlepas dari semua masalah dengan pengembang membingungkan NULL, NULL memiliki kelemahan lain yang sangat serius: Kinerja

Kolom NULL'able adalah bencana dari perspektif kinerja. Pertimbangkan bilangan bulat aritmatika sebagai contoh. Dalam dunia yang waras tanpa NULL, "mudah" untuk membuat aritmatika integer integer dalam kode engine basis data menggunakan instruksi SIMD untuk melakukan hampir semua perhitungan dengan kecepatan lebih cepat dari 1 baris per siklus CPU. Namun, saat Anda memperkenalkan NULL, Anda harus menangani semua kasus khusus yang dibuat NULL. Set instruksi CPU modern (baca: x86 / x64 / ARM dan juga logika GPU) sama sekali tidak dilengkapi untuk melakukan ini secara efisien.

Pertimbangkan pembagian sebagai contoh. Pada level yang sangat tinggi, ini adalah logika yang Anda butuhkan dengan integer non null:

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

Dengan NULL, ini menjadi sedikit lebih rumit. Bersama dengan bAnda akan membutuhkan indikator jika bnol dan sama untuk a. Cek sekarang menjadi:

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

Aritmatika NULL secara signifikan lebih lambat untuk berjalan pada CPU modern daripada aritmatika bukan nol (dengan faktor sekitar 2-3x).

Semakin buruk saat Anda memperkenalkan SIMD. Dengan SIMD, CPU Intel modern dapat melakukan pembagian integer 4 x 32-bit dalam satu instruksi, seperti ini:

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

Sekarang, ada cara untuk menangani NULL di tanah SIMD juga, tetapi ini membutuhkan penggunaan lebih banyak vektor dan register CPU dan melakukan beberapa penyembunyian bit pintar. Bahkan dengan trik yang baik, penalti kinerja aritmatika integer NULL merayap ke dalam kisaran 5-10x lebih lambat untuk ekspresi yang bahkan relatif sederhana.

Sesuatu seperti di atas berlaku untuk agregat dan sampai batas tertentu, untuk bergabung juga.

Dengan kata lain: Keberadaan NULL dalam SQL adalah ketidakcocokan impedansi antara teori database dan desain aktual komputer modern. Ada alasan yang cukup bagus NULL membingungkan pengembang - karena integer tidak bisa NULL dalam sebagian besar bahasa pemrograman yang waras - itu bukan cara komputer bekerja.

Thomas Kejser
sumber
10

Pertanyaan menarik.

Yang bisa saya pikirkan hanyalah bahwa, sebagai pengembang aplikasi, Anda tidak perlu menguji NULL dan kemungkinan nilai data yang tidak ada (misalnya, string kosong untuk string).

Ini lebih rumit dari itu. Null memiliki sejumlah arti yang berbeda dan satu alasan yang sangat penting untuk tidak mengizinkan nol dalam banyak kolom adalah bahwa ketika kolom tersebut nol, ini berarti satu dan hanya satu hal (yaitu tidak muncul di bagian luar). Selain itu memungkinkan Anda untuk menetapkan standar minimum entri data yang sangat membantu.

Tapi apa yang Anda lakukan dalam hal tanggal, waktu, dan waktu (SQL Server 2008)? Anda harus menggunakan tanggal yang bersejarah atau bottom-up.

Itu menggambarkan masalah dengan nulls segera, yaitu bahwa nilai yang disimpan dalam tabel dapat berarti "nilai ini tidak berlaku" atau "kita tidak tahu." Dengan string, string kosong dapat berfungsi sebagai "ini tidak berlaku" tetapi dengan tanggal dan waktu, tidak ada konvensi seperti itu karena tidak ada nilai valid yang secara konvensional berarti ini. Biasanya di sana Anda akan mandek menggunakan NULL.

Ada beberapa cara untuk mengatasi hal ini (dengan menambahkan lebih banyak hubungan dan bergabung) tetapi hal-hal itu menimbulkan masalah kejelasan semantik yang sama persis dengan yang dimiliki NULL dalam database. Untuk database ini saya tidak akan khawatir tentang ini. Tidak ada yang bisa Anda lakukan untuk itu.

Sunting: Satu area di mana NULL sangat diperlukan adalah dalam kunci asing. Di sini mereka biasanya hanya memiliki satu makna, identik dengan nol dalam makna gabungan luar. Ini pengecualian untuk masalah tentu saja.

Chris Travers
sumber
10

Artikel Wikipedia tentang SQL Null memiliki beberapa komentar menarik tentang nilai NULL, dan sebagai jawaban database-agnostik, selama Anda mengetahui dampak potensial dari memiliki nilai NULL untuk RDBMS spesifik Anda, mereka dapat diterima dalam desain Anda. Jika tidak, Anda tidak akan dapat menentukan kolom sebagai nullable.

Perlu diketahui bagaimana RDBMS Anda menangani mereka dalam operasi SELECT seperti matematika, dan juga dalam Indeks.

Derek Downey
sumber
-12

Wow, jawaban yang benar "Jangan izinkan NULL ketika Anda tidak harus melakukannya karena mereka menurunkan kinerja" adalah jawaban yang dinilai terakhir. Saya akan mengangkatnya dan menguraikannya. Ketika RDBMS memungkinkan NULL untuk kolom non-jarang, kolom itu ditambahkan ke bitmap yang melacak apakah nilainya NULL untuk setiap baris individual. Jadi dengan menambahkan kemampuan NULL ke kolom dalam tabel di mana semua kolom tidak mengizinkan NULL, Anda menambah ruang penyimpanan yang diperlukan untuk menyimpan tabel. Selanjutnya, Anda memerlukan RDBMS untuk membaca dan menulis ke bitmap, menurunkan kinerja pada semua operasi.

Lebih lanjut, dalam sejumlah contoh, memungkinkan NULL akan merusak 3NF. Meskipun saya bukan penganut 3NF seperti kebanyakan kolega saya, pertimbangkan skenario berikut:

Di tabel Orang ada kolom, yang disebut DateOfDeath, yang dapat dibatalkan. Jika seseorang telah meninggal, itu akan diisi dengan DateOfDeath mereka, jika tidak maka NULL akan ditinggalkan. Ada juga kolom bit yang tidak dapat dibatalkan yang disebut IsAlive. Kolom ini diatur ke 1 jika orang tersebut masih hidup, dan 0 jika orang itu sudah mati. Sebagian besar prosedur tersimpan menggunakan kolom IsAlive, mereka hanya peduli jika seseorang hidup, bukan DateOfDeath mereka.

Namun, kolom IsAlive memecah normalisasi database, karena sepenuhnya turunan dari DateOfDeath. Tetapi karena IsAlive terprogram ke dalam mayoritas SP, solusi langsung adalah membuat DateOfDeath tidak dapat dibatalkan, dan menetapkan nilai default ke kolom jika orang tersebut masih hidup. Beberapa SP yang menggunakan DateOfDeath kemudian dapat ditulis ulang untuk memeriksa kolom IsAlive, dan hanya menghormati DateOfDeath jika orang tersebut tidak hidup. Sekali lagi, karena mayoritas SP hanya peduli tentang IsAlive (sedikit) dan bukan DateOfDeath (tanggal) menggunakan pola ini mempercepat akses.

Skrip T-SQL yang berguna untuk menemukan kolom yang dapat dibatalkan tanpa NULL di semua skema adalah:

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;

Jika Anda menjalankan ini pada salinan basis data produksi Anda, Anda dapat menemukan kolom yang ditandai pengembang sebagai memungkinkan NULL yang tidak memiliki NULL dalam praktiknya. Sebagian besar dari ini dapat ditandai sebagai NOT NULL, sehingga meningkatkan kinerja dan menurunkan ruang penyimpanan.

Mungkin tidak mungkin untuk menghilangkan semua NULL di semua tabel dan masih memiliki desain yang bersih, tetapi ada keuntungan yang cukup besar dalam menghilangkan NULL sebanyak mungkin. Pengoptimal bekerja lebih cepat dengan informasi ini, dan jika Anda bisa menghilangkan semua NULL dalam sebuah tabel, Anda bisa mendapatkan kembali ruang penyimpanan yang cukup besar.

Saya tahu bahwa kinerja bukanlah sesuatu yang banyak dipikirkan oleh DBA, tetapi Anda hanya dapat membuang sejumlah memori dan daya prosesor pada suatu solusi, suatu titik yang harus Anda mulai pikirkan tentang desain logis dan fisik. .

Juga perhatikan bahwa ini hanya untuk RDBMSes yang benar dan saya mendasarkan bagian teknis dari jawaban saya dari SQL Server. T-SQL yang terdaftar untuk menemukan kolom yang dapat dibatalkan tanpa null juga dari SQL Server.

Matthew Sontum
sumber
1
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Paul White