Dalam pengalaman saya, banyak proyek yang saya baca di masa lalu tidak memiliki definisi hubungan dalam database, sebaliknya mereka hanya mendefinisikannya dalam kode sumber. Jadi saya bertanya-tanya apa kelebihan / kekurangan dari mendefinisikan hubungan antara tabel dalam database dan dalam kode sumber? Dan pertanyaan yang lebih luas adalah tentang fitur-fitur canggih lainnya dalam database modern seperti kaskade, pemicu, prosedur ... Ada beberapa poin dalam pikiran saya:
Dalam database:
Koreksi data dari desain. Cegah kesalahan aplikasi yang dapat menyebabkan data tidak valid.
Kurangi round trip jaringan ke aplikasi saat memasukkan / memperbarui data karena aplikasi harus membuat lebih banyak kueri untuk memeriksa integritas data.
Dalam kode sumber:
Lebih fleksibel.
Lebih baik ketika melakukan penskalaan ke banyak basis data, karena terkadang hubungannya bisa lintas basis data.
Lebih banyak kontrol atas integritas data. Basis data tidak harus memeriksa setiap kali aplikasi memodifikasi data (kompleksitasnya bisa O (n) atau O (n log n) (?)). Sebaliknya, itu didelegasikan ke aplikasi. Dan saya pikir menangani integritas data dalam aplikasi akan menyebabkan lebih banyak pesan kesalahan verbose daripada menggunakan database. Misalnya: ketika Anda membuat server API, jika Anda menentukan hubungan dalam database, dan ada yang salah (seperti entitas yang direferensikan tidak ada), Anda akan mendapatkan SQL Exception dengan pesan. Cara sederhana adalah mengembalikan 500 ke klien bahwa ada "kesalahan server internal" dan klien tidak akan tahu apa yang salah. Atau server dapat mem-parsing pesan untuk mencari tahu apa yang salah, yang merupakan cara yang jelek dan rawan menurut saya. Jika Anda membiarkan aplikasi menangani ini,
Apakah ada hal lain?
Sunting: seperti yang ditunjukkan Kilian, poin saya tentang kinerja & integritas data sangat keliru. Jadi saya mengedit untuk memperbaiki maksud saya di sana. Saya benar-benar mengerti bahwa membiarkan basis data mengatasinya akan menjadi pendekatan yang lebih efisien dan kuat. Silakan periksa pertanyaan yang diperbarui dan berikan beberapa pemikiran tentangnya.
Sunting: terima kasih semuanya. Jawaban yang saya terima semuanya menunjukkan bahwa kendala / hubungan harus didefinisikan dalam database. :) Saya punya satu pertanyaan lagi, karena cukup di luar cakupan pertanyaan ini, saya baru saja mempostingnya sebagai pertanyaan terpisah: Menangani kesalahan basis data untuk server API . Silakan tinggalkan beberapa wawasan.
Jawaban:
TL; DR: Kendala hubungan harus ada dalam database.
Aplikasi Anda tidak cukup besar.
Anda benar, memang, bahwa menegakkan hubungan di seluruh basis data mungkin memerlukan penegakannya dalam aplikasi.
Saya akan menunjukkan, bahwa Anda harus terlebih dahulu memeriksa dokumentasi perangkat lunak database yang Anda gunakan, dan memeriksa penawaran produk yang ada. Misalnya, ada penawaran pengelompokan di atas Postgres dan MySQL.
Dan bahkan jika Anda berakhir perlu memiliki beberapa validasi dalam aplikasi, tidak membuang bayi dengan air mandi . Lagi pula, semakin sedikit yang harus Anda lakukan, semakin baik Anda.
Akhirnya, jika Anda khawatir tentang masalah skalabilitas di masa depan, saya khawatir aplikasi Anda harus mengalami perubahan signifikan sebelum dapat berkembang. Sebagai aturan praktis, setiap kali Anda tumbuh 10x, Anda harus mendesain ulang ... jadi jangan tenggelamkan terlalu banyak uang untuk gagal mengantisipasi masalah skalabilitas, dan alih-alih gunakan uang untuk benar-benar mencapai titik di mana Anda memiliki masalah tersebut.
Aplikasi Anda tidak cukup benar.
Berapa kemungkinan bahwa database yang Anda gunakan memiliki implementasi cek yang salah dibandingkan dengan kemungkinan bahwa aplikasi Anda memiliki implementasi cek yang salah?
Dan yang mana yang paling sering Anda ubah?
Saya bertaruh pada database yang benar, kapan saja .
Pengembang Anda tidak berpikir cukup terdistribusi.
Bendera Merah ! 1
Jika Anda berpikir:
maka Anda gagal masalah konkurensi paling dasar: proses / utas lain mungkin menambahkan catatan saat Anda pergi.
Jika Anda berpikir:
maka Anda gagal untuk menghitung MVCC: tampilan database yang Anda miliki adalah snapshot pada saat transaksi Anda dimulai; itu tidak menunjukkan semua pembaruan yang terjadi, dan mungkin bahkan tidak dilakukan.
Mempertahankan kendala di beberapa sesi adalah masalah yang sangat sulit, senang itu diselesaikan dalam database Anda.
1 Kecuali jika database Anda mengimplementasikan properti Serializable dengan benar; tetapi sedikit yang benar-benar melakukannya.
Terakhir:
Jangan parsing pesan kesalahan , jika Anda menggunakan basis data tingkat produksi apa pun itu harus mengembalikan kesalahan terstruktur. Anda akan memiliki beberapa kode kesalahan, setidaknya, untuk menunjukkan apa yang mungkin salah, dan berdasarkan kode ini Anda dapat membuat pesan kesalahan yang sesuai.
Perhatikan bahwa sebagian besar kali kode sudah cukup: jika Anda memiliki kode kesalahan yang memberi tahu Anda bahwa kunci asing yang dirujuk tidak ada, maka kemungkinan tabel ini hanya memiliki satu kunci asing, sehingga Anda tahu dalam kode apa masalahnya. .
Juga, dan mari kita jujur di sini, sebagian besar kali Anda tidak akan menangani kesalahan dengan anggun. Hanya karena ada begitu banyak dari mereka dan Anda akan gagal menjelaskan semuanya ...
... yang hanya terkait dengan titik kebenaran di atas. Setiap kali Anda melihat "500: Galat Server Internal" karena kendala basis data dipecat dan tidak ditangani, itu berarti basis data menyelamatkan Anda, karena Anda baru saja lupa menanganinya dalam kode.
sumber
Ini adalah poin yang sangat keliru. Database dibuat untuk tujuan ini. Jika Anda memerlukan pemeriksaan integritas data (dan jika Anda pikir Anda tidak membutuhkannya, Anda mungkin salah), kemudian membiarkan database menanganinya hampir pasti lebih efisien dan lebih rentan kesalahan daripada melakukannya dalam logika aplikasi.
sumber
Kendala harus ada dalam database Anda, karena (dengan kehendak terbaik di dunia), aplikasi Anda tidak akan menjadi satu-satunya hal yang pernah mengakses database ini.
Pada titik tertentu, mungkin perlu ada perbaikan skrip di dalam basis data, atau Anda mungkin perlu memigrasikan data dari satu tabel ke tabel lainnya saat penyebaran.
Selain itu Anda mungkin mendapatkan persyaratan lain misalnya "Pelanggan besar X benar-benar membutuhkan lembar data excel ini diimpor ke dalam basis data aplikasi kami sore ini", di mana Anda tidak akan memiliki kemewahan mengadaptasi kode aplikasi Anda agar sesuai ketika skrip SQL kotor akan menyelesaikannya pada waktunya.
Di sinilah integritas tingkat basis data akan menghemat daging Anda.
Selain itu, bayangkan pengembang yang mengambil peran Anda di perusahaan ini setelah Anda pergi dan kemudian bertugas membuat perubahan basis data.
Apakah dia akan membencimu jika tidak ada batasan FK dalam database sehingga dia bisa mengetahui hubungan apa yang dimiliki tabel sebelum dia mengubahnya? ( Petunjuk, jawabannya adalah ya )
sumber
Anda harus memiliki relasi dalam database.
Seperti jawaban jawaban lainnya, kinerja pemeriksaan kendala akan jauh lebih baik di dalam basis data itu daripada di dalam aplikasi Anda. Pengecekan batasan basis data adalah salah satu hal yang dimiliki oleh database.
Jika Anda membutuhkan fleksibilitas tambahan - mis. Referensi lintas basis data yang Anda catat - maka Anda dapat menghapus kendala dengan sengaja dan dengan pertimbangan. Memiliki konsistensi dalam basis data Anda berarti Anda memiliki opsi untuk memodifikasi kendala tersebut, dan kepastian integritas referensial.
sumber
Bisakah Anda benar-benar mampu menulis dan menguji kode penegakan integritas referensial ketika Anda memiliki kode penyelesaian masalah domain untuk ditulis?
sumber
Jika Anda tidak memvalidasi integritas data Anda, kendala, hubungan dll di tingkat database yang berarti itu jauh lebih mudah bagi siapa pun dengan akses basis data produksi (melalui klien lain termasuk alat akses DB) untuk mengacaukan data Anda.
Merupakan praktik yang bagus untuk menegakkan integritas data seketat mungkin di tingkat basis data. Percayalah, ini akan menghemat banyak sakit kepala dari waktu ke waktu dalam sistem non-sepele. Anda juga akan mengambil kesalahan logika aplikasi atau kesalahan persyaratan bisnis dan inkonsistensi lebih cepat jika dipikirkan dengan cermat.
Sebagai catatan tambahan, rancang basis data Anda dengan cara yang dinormalisasi dan serata mungkin. Tidak ada tabel "Tuhan". Habiskan banyak upaya merancang database Anda sesederhana mungkin, idealnya dengan banyak tabel kecil yang didefinisikan secara individual dengan sangat baik, dengan satu tanggung jawab dan divalidasi dengan hati-hati pada semua kolom. Basis data adalah penjaga terakhir integritas data Anda. Ini mewakili Keep of the Castle.
sumber
Kebanyakan orang pada dasarnya mengatakan "ya, secara umum kamu harus selalu mendefinisikan hubungan dalam database". Tetapi jika disiplin dalam ilmu komputer sangat mudah, kita akan disebut "Pembaca Manual Perangkat Lunak" dan bukannya "Insinyur Perangkat Lunak". Saya benar-benar setuju bahwa kendala harus ada dalam database, kecuali ada alasan bagus untuk itu , jadi izinkan saya hanya memberikan beberapa alasan yang mungkin dianggap baik dalam situasi tertentu:
Kode Gandakan
Terkadang sejumlah fungsionalitas yang dapat ditangani oleh basis data secara alami akan ada dalam kode aplikasi. Jika menambahkan sesuatu seperti kendala ke basis data akan berlebihan, mungkin lebih baik tidak menduplikasi fungsionalitas, karena Anda melanggar prinsip KERING, dan Anda mungkin memperburuk tindakan juggling menjaga database dan kode aplikasi tetap sinkron.
Upaya
Jika database Anda sudah melakukan apa yang perlu dilakukan tanpa menggunakan fitur-fitur canggih, Anda mungkin ingin mengevaluasi di mana waktu, uang, dan usaha Anda harus ditempatkan. Jika menambahkan kendala akan mencegah kegagalan bencana dan dengan demikian menghemat banyak uang bagi perusahaan Anda, maka itu mungkin layak dilakukan. Jika Anda menambahkan kendala yang harus ditahan, tetapi sudah dijamin tidak akan pernah dilanggar, Anda membuang-buang waktu dan mencemari basis kode Anda. Dijamin adalah kata yang berlaku di sini.
Efisiensi
Ini biasanya bukan alasan yang baik tetapi dalam beberapa kasus Anda mungkin memiliki persyaratan kinerja tertentu. Jika kode aplikasi dapat mengimplementasikan fungsi tertentu dengan cara yang lebih cepat daripada database, dan Anda memerlukan kinerja ekstra, Anda mungkin perlu mengimplementasikan fitur dalam kode aplikasi.
Kontrol
Agak terkait dengan efisiensi. Kadang-kadang Anda membutuhkan kontrol berbutir halus tentang bagaimana fitur diimplementasikan, dan kadang-kadang memiliki basis data menanganinya menyembunyikannya di balik kotak hitam yang perlu Anda buka.
Poin Penutupan
Hal terakhir yang akan saya katakan adalah bahwa Anda akan tahu jika Anda tidak seharusnya menempatkan fungsionalitas dalam database. Jika Anda tidak yakin, Anda mungkin lebih baik menggunakan fitur basis data, karena mereka biasanya bekerja dengan sangat baik.
sumber
Seperti biasa, ada banyak jawaban. Bagi saya, saya menemukan aturan sederhana (baik itu hanya bekerja untuk pendekatan model-sentris). Biasanya, saya hanya fokus pada berbagai lapisan aplikasi.
Jika model terdiri dari beberapa entitas dan ada dependensi antara entitas, layer persisten harus mencerminkan dependensi tersebut dengan kemungkinannya. Jadi jika Anda menggunakan RDBMS, maka Anda juga harus menggunakan kunci asing. Alasannya sederhana. Dengan begitu data selalu valid secara struktural.
Setiap instance yang melakukan pekerjaan pada layer persisten ini dapat mengandalkannya. Saya berasumsi, bahwa Anda merangkum lapisan ini melalui antarmuka (layanan). Jadi, inilah titik di mana desain berakhir dan dunia nyata dimulai.
Melihat poin Anda, terutama referensi lintas basis data . Dalam hal itu, ya seharusnya tidak ada referensi yang diterapkan dalam RDBMS itu sendiri, tetapi dalam layanan. Tetapi sebelum mengikuti cara ini, bukankah akan lebih baik untuk mempertimbangkan ini selama desain?
Berarti, jika saya sudah tahu, bahwa ada bagian yang perlu disimpan dalam DB yang berbeda, maka saya dapat menempatkannya di sana dan mendefinisikannya sebagai model terpisah. Baik?
Anda juga menunjukkan bahwa menerapkan ini dalam kode lebih fleksibel . Benar, tetapi bukankah itu terdengar seperti Anda sedang berhadapan dengan desain yang tidak lengkap? Tanyakan kepada diri sendiri, mengapa Anda membutuhkan lebih banyak fleksibilitas?
Masalah kinerja, karena pemeriksaan integritas di DB tidak nyata. RDBMS dapat memeriksa hal-hal seperti itu lebih cepat daripada implementasi apa pun oleh Anda. Mengapa? Nah, Anda harus berurusan dengan gangguan media, RDBMS tidak. Dan itu dapat mengoptimalkan pemeriksaan tersebut dengan menggunakan statistiknya juga
Jadi Anda lihat, semuanya kembali ke desain. Tentu saja Anda bisa mengatakannya sekarang, tetapi bagaimana jika muncul persyaratan yang tidak diketahui, pengubah permainan? Ya itu mungkin terjadi, tetapi perubahan tersebut harus dirancang dan direncanakan juga. ;Hai)
sumber
Anda memiliki beberapa jawaban yang sangat bagus tetapi beberapa poin lagi
Integritas data adalah apa yang dirancang untuk dilakukan oleh suatu basis data
Melakukan konkurensi yang tepat seperti penghapusan FK di tingkat aplikasi akan sangat menghebohkan
Keahlian dalam integritas data adalah dengan DBA
Pada tingkat program Anda memasukkan, memperbarui, memperbarui massal, memasukkan massal, menghapus massal ...
Thin client, thin client, mobile client ....
Integritas data bukan keahlian seorang programmer - banyak kode duplikat dan seseorang akan mengacaukan itu
Katakanlah Anda diretas - Anda berada dalam masalah, tetapi seorang peretas dapat melakukan banyak kerusakan melalui lubang kecil jika tidak ada perlindungan integritas di database
Anda mungkin perlu memanipulasi data secara langsung melalui SQL atau TSQL.
Tidak ada yang akan mengingat semua aturan data
sumber
Pertanyaan Anda tidak masuk akal: jika Anda bisa mengubah database, itu kodenya, jika Anda tidak bisa mengubah database, Anda harus membuat batasan Anda di tempat lain.
Basis data yang dapat Anda ubah adalah setiap bit kode sebanyak baris ruby, javascript, c # atau ada.
Pertanyaan tentang di mana menempatkan kendala dalam sistem Anda harus mengarah pada keandalan, biaya, dan kemudahan pengembangan.
sumber
Ada banyak jawaban bagus di sini. Saya akan menambahkan bahwa jika Anda memiliki aplikasi yang ditulis dalam bahasa Y, Anda dapat membuat kode seperti basis data kendala di Y. Dan kemudian seseorang ingin mengakses database Anda menggunakan bahasa Z, Anda harus menulis kode yang sama lagi. Tuhan membantu Anda jika implementasinya tidak persis sama. Atau ketika pengguna bisnis yang berpengetahuan luas terhubung ke database Anda menggunakan Microsoft Access.
Pengalaman saya memberi tahu saya bahwa ketika orang tidak ingin menggunakan batasan database, itu karena mereka sebenarnya mencoba melakukan sesuatu dengan cara yang salah. Misalnya, mereka mencoba untuk memuat data secara massal, dan mereka ingin membiarkan kolom tidak-nol nol, untuk sementara waktu. Mereka berniat untuk "memperbaikinya nanti" karena situasi yang membuat batasan bukan nol kritis "tidak mungkin terjadi dalam kasus ini." Contoh lain bisa terjadi ketika mereka mencoba memasukkan dua tipe data yang berbeda ke dalam tabel yang sama.
Orang yang lebih berpengalaman akan mengambil langkah mundur dan menemukan solusi yang tidak melibatkan upaya untuk melewati batasan. Solusinya bisa jadi kendala saja sudah tidak layak lagi karena bisnisnya berubah, tentunya.
sumber