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?
database-design
null
Thomas Stringer
sumber
sumber
Jawaban:
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.
sumber
birth_date
tempat Anda menyimpan tanggal lahir? Jika tanggal lahir tidak diketahui maka jangan masukkan tanggal lahirbirth_date
. Null adalah bencana.1900-01-01
untuk 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.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” .
sumber
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.
sumber
null
, dan logika multi-nilai yang ditetapkan pengguna untuk pergi bersama mereka: pBiarkan 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.
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.
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.
sumber
TerminationDate
dalam catatan karyawan, tetapi memiliki tabel diTerminatedEmployee
mana karyawan dipindahkan ke (tidak disalin) oleh aplikasi ketika mereka diberhentikan. Jelas ini berfungsi baik dengan tabel Akun karena tidak akan ada akun tertaut di atasTerminatedEmployee
meja. 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.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:
Dengan NULL, ini menjadi sedikit lebih rumit. Bersama dengan
b
Anda akan membutuhkan indikator jikab
nol dan sama untuka
. Cek sekarang menjadi: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:
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.
sumber
Pertanyaan menarik.
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.
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.
sumber
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.
sumber
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:
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.
sumber