Saya memiliki aplikasi (data disimpan dalam PostgreSQL), di mana sebagian besar bidang dalam tabel selalu tidak nol, tetapi skema untuk tabel ini tidak memberlakukan ini. Sebagai contoh, lihat tabel palsu ini:
CREATE TABLE "tbl" (
"id" serial,
"name" varchar(40),
"num" int,
"time" timestamp
PRIMARY KEY ("id"),
UNIQUE ("id")
);
Juga name
, num
, time
tidak secara eksplisit dinyatakan sebagai NOT NULL
, dalam kenyataannya mereka, karena penegakan terjadi di sisi aplikasi.
Perasaan saya adalah bahwa itu harus diubah, tetapi sebaliknya adalah bahwa tingkat aplikasi memastikan bahwa nilai nol tidak dapat muncul di sini dan tidak ada orang lain yang secara manual memodifikasi tabel.
Pertanyaan saya adalah : Apa manfaatnya (kinerja, penyimpanan, konsistensi, sesuatu yang lain) dan kelemahannya (dengan asumsi saya sudah memverifikasi bahwa tidak ada null yang ada saat ini, dan dari logika bisnis seharusnya tidak ada null) dengan menetapkan NOT NULL
kendala eksplisit ?
Kami memiliki proses peninjauan kode yang baik dan dokumentasi yang cukup baik, sehingga kemungkinan bahwa beberapa orang baru akan melakukan sesuatu yang melanggar batasan ini tidak benar-benar cukup untuk membenarkan perubahan.
Ini bukan keputusan saya, jadi inilah tepatnya mengapa saya mencari pembenaran lain. Menurut pendapat saya, jika sesuatu tidak bisa menjadi nol dan database memungkinkan Anda menentukan bahwa sesuatu itu bukan nol - maka lakukan saja. Apalagi jika ubahannya super sederhana.
sumber
NOT NULL
kendala tidak memiliki efek langsung pada ukuran penyimpanan. Tentu saja, dengan semua kolom didefinisikanNOT NULL
, tidak mungkin ada bitmap nol untuk memulai. Di sisi lain: ukuran penyimpanan biasanya jauh lebih kecil jika Anda menggunakan NULL alih-alih nilai "kosong" atau dummy untuk kolom tanpa nilai aktual, karena bitmap null relatif jauh lebih kecil (kecuali untuk kasus tepi langka).Jawaban:
Apa yang terjadi ketika seorang programmer baru tiba dan harus menulis aplikasi terhadap db itu? Mereka tidak tahu bidang x itu seharusnya
NOT NULL
.Program lain mungkin berasumsi bahwa semua bidang x adalah
NOT NULL
untuk melakukan penghitungan katakan, tetapi beberapa sekarang adalahNULL
karena program baru, yang mengarah ke kesalahan yang tidak konsisten dan sulit dilacak.IMHO itu selalu yang terbaik untuk menegakkan aturan integritas data sedekat mungkin dengan data, yaitu dalam database. Dengan begitu, aplikasi dan / atau programmer baru tidak dapat mengacaukan data Anda.
Pemrogram, aplikasi, bahasa dan kerangka kerja datang dan pergi. Data dan basis data cenderung bertahan. Basis data adalah garis pertahanan terakhir Anda terhadap data yang tidak konsisten dan berpotensi salah.
Manfaatkan secara maksimal mekanisme penegakan kendala integritas database Anda, bahkan dengan mengorbankan kinerja. Sistem lambat yang menghasilkan hasil yang benar jauh lebih unggul daripada yang cepat yang salah!
sumber
IMHO it is always best to enforce data integrity rules as near to the data as possible
ini sebenarnya sama dengan firasat yang saya tulis. Dan inilah tepatnya mengapa saya mencari pembenaran yang nyata. Kami memiliki ulasan kode di tempat dan dokumentasi yang baik, sehingga kekhawatiran tentang pengembang baru yang tidak mengetahui sesuatu tidak cukup untuk membenarkan perubahan.REAL PROGRAMMERS
membaca semua (atau bahkan ada) dari dokumentasi sebelum terjebak dalam sebuah prject di mana mereka berada pada tenggat waktu yang ketat?Seperti yang sudah dikutip oleh orang lain dalam komentar, menambahkan
NOT NULL
spesifikasi tabel Anda dapat meningkatkan kinerja kueri Anda secara signifikan (selain alasan metodologi yang sangat baik yang dinyatakan dalam jawaban lain).Alasannya adalah bahwa optimizer kueri, mengetahui bahwa kolom tidak dapat memiliki
NULL
nilai, dapat mengecualikan pengujian khusus untuk nilai-nilai tersebut, seperti dalam kasusNOT IN
vs.NOT EXISTS
Misalnya , Anda dapat melihat blog ini , yang menunjukkan bahwa tidak mendeklarasikan bidangNOT NULL
(saat tabel berisi selalu nilai-nilai bukan nol) dengan kueri tertentu meningkatkan waktu pelaksanaan 500%. Hasilnya ditampilkan untuk SQL Server, tetapi perilaku serupa dapat hadir dalam DBMS relasional lainnya, seperti milik Anda (belum lagi fakta bahwa database Anda dapat diangkut ke sistem lain). Aturan umum yang dapat Anda asumsikan adalah bahwa ketika lebih banyak informasi tersedia untuk optimizer kueri, maka rencana akses yang lebih efisien dapat dihasilkan.sumber
NOT NULL
karena berbagai alasan, tidak ada argumen tentang itu. Tetapi tautan ke blog tentang SQL Server tidak berlaku untuk Postgres dan tidak membuktikan implikasi kinerja yang Anda sebutkan. Tidak mengatakan tidak ada, tetapi saya ingin melihat bukti nyata .not in
untuk kolom nullable berbeda, jadi harus ada beberapa perbedaan dalam rencana antara keduanya?Implikasi ruang
The implikasi ruang dibicarakan di posting ini dengan @Erwin Brandstetter
Singkatnya, Anda akan menyimpan satu
totalColumns - 8
bit yang dibulatkan ke byte terdekat (atauMAXALIGN
), jika database Anda memilikiNOT NULL
Implikasi kinerja
Namun, dalam posting ini di SE oleh @Erwin Brandstetter , katanya
@Renzo memiliki jawaban yang berbicara tentang implikasi kinerja - saya akan menganggap tidak ada yang berlaku untuk PostgreSQL . Saya tidak dapat menemukan apa pun yang mendukung semua itu sebagai relevan dengan PostgreSQL. Siklus apa pun yang disimpan tidak dapat dikuantifikasi bahkan dalam kueri yang paling mendasar sekalipun.
Selain itu saya menjalankan beberapa tes untuk melihat apakah NULL-indeks lebih cepat, dan saya tidak bisa membuktikannya. Anda dapat menemukan utas yang sangat berguna ini oleh Scott Marlowe di milis yang berbicara tentang perencana kueri di 9.1 yang dapat menggunakan indeks parsial pada klausa WHERE yang berbeda. Saya menguji ini dengan menjalankan yang berikut ini
Sekarang saya membuat indeks,
Dalam kedua kasus ini perencana dapat menggunakan indeks saat memilih
= 10
dan menggunakan pemindaian seq saat mencari masing-masing NULL atau 0. Kedua indeks parsial memiliki ukuran yang sama. Dan, indeks lengkap (tidak ditampilkan) memiliki ukuran yang sama. Mengikuti metodologi yang sama saya memuat tabel dengan satu urutan1..1e5
, dan satu nilai nol / 0, dan urutan lain dari1..1e5
. Kedua metode dapat menemukan nol / 0 dengan indeks yang mencakup seluruh tabel.TLDR; Ringkasan
Saya tidak dapat membuktikan sesuatu dengan cara apa pun pada sebagian besar masalah kinerja yang saya pikir layak untuk diuji termasuk ketidakcukupan perencana. Manfaat menggunakan null untuk menghemat ram adalah nyata. Ruang disk yang disimpan dengan tidak menggunakan null dapat diabaikan, dan itu terlalu berlebihan pada tabel dengan satu
NULLABLE
kolom, atau kurang dari 8 kolom. Dalam kasus tersebut tidak ada ruang disk yang disimpan.sumber