Ada apa dengan kunci asing?

259

Saya ingat pernah mendengar Joel Spolsky menyebutkan di podcast 014 bahwa ia jarang menggunakan kunci asing (jika saya ingat dengan benar). Namun, bagi saya mereka tampaknya sangat penting untuk menghindari duplikasi dan masalah integritas data selanjutnya di seluruh database Anda.

Apakah orang memiliki alasan kuat mengapa (untuk menghindari diskusi yang sejalan dengan prinsip Stack Overflow)?

Sunting: "Saya belum punya alasan untuk membuat kunci asing, jadi ini mungkin alasan pertama saya untuk benar-benar membuat kunci asing."

Zolomon
sumber
9
Saya tidak berpikir Joel tidak menggunakan FK, hanya saja dia tidak membuat database menegakkan mereka. Logikanya, mereka masih FK!
Daren Thomas
6
Dia bilang dia tidak menggunakan kunci asing, tapi aku setuju dengan Daren bahwa yang dia maksud adalah dia tidak menggunakan kunci asing. Kolom dalam satu tabel yang nilainya seharusnya diambil dari kunci primer / unik tabel lain ADALAH kunci asing, baik Anda menambahkan kendala atau tidak.
Tony Andrews
22
... Umumnya bodoh untuk tidak menambahkan kendala: itu MENJAMIN integritas setiap saat, bahkan jika ada bug dalam kode aplikasi atau jika Anda bekerja di belakang layar melakukan data "perbaiki".
Tony Andrews
2
+1 Untuk komentar Tony. Ada terlalu banyak kebingungan antara fitur dan konsep logis kunci asing di luar sana.
JohnFx
4
@DanMan, saya tidak tahu dari mana Anda mendapatkan kesan itu. Saya benar-benar mengatakan di atas, "Pada umumnya bodoh untuk tidak menambahkan kendala: itu MEMASTIKAN integritas setiap saat"
Tony Andrews

Jawaban:

352

Alasan menggunakan Kunci Asing:

  • Anda tidak akan mendapatkan Baris Yatim
  • Anda bisa mendapatkan perilaku "on delete cascade" yang bagus, secara otomatis membersihkan tabel
  • mengetahui tentang hubungan antar tabel dalam basis data membantu Pengoptimal merencanakan pertanyaan Anda untuk eksekusi yang paling efisien, karena dapat memperoleh perkiraan yang lebih baik tentang bergabung dengan kardinalitas.
  • FK memberikan petunjuk yang cukup besar tentang statistik apa yang paling penting untuk dikumpulkan pada database, yang pada gilirannya mengarah pada kinerja yang lebih baik
  • mereka memungkinkan semua jenis dukungan yang dihasilkan secara otomatis - ORM dapat menghasilkan sendiri, alat visualisasi akan dapat membuat tata letak skema yang bagus untuk Anda, dll.
  • seseorang yang baru dalam proyek ini akan masuk ke dalam aliran sesuatu dengan lebih cepat karena hubungan implisit didokumentasikan secara eksplisit

Alasan untuk tidak menggunakan Kunci Asing:

  • Anda membuat DB berfungsi ekstra pada setiap operasi CRUD karena harus memeriksa konsistensi FK. Ini bisa menjadi biaya besar jika Anda memiliki banyak churn
  • dengan menegakkan hubungan, FK menentukan urutan di mana Anda harus menambah / menghapus hal-hal, yang dapat menyebabkan penolakan oleh DB untuk melakukan apa yang Anda inginkan. (Memang, dalam kasus seperti itu, apa yang Anda coba lakukan adalah membuat Orphaned Row, dan itu biasanya bukan hal yang baik). Ini sangat menyakitkan ketika Anda melakukan pembaruan batch besar, dan Anda memuat satu tabel sebelum yang lain, dengan tabel kedua menciptakan keadaan yang konsisten (tetapi jika Anda melakukan hal semacam itu jika ada kemungkinan bahwa beban kedua gagal dan Anda basis data sekarang tidak konsisten?).
  • terkadang Anda tahu sebelumnya bahwa data Anda akan menjadi kotor, Anda menerimanya, dan Anda ingin DB menerimanya
  • kamu hanya malas :-)

Saya pikir (saya tidak yakin!) Bahwa sebagian besar database yang mapan menyediakan cara untuk menentukan kunci asing yang tidak ditegakkan, dan hanya sedikit metadata. Karena tanpa penegakan menghapuskan setiap alasan untuk tidak menggunakan FK, Anda mungkin harus menempuh rute itu jika ada alasan di bagian kedua yang berlaku.

SquareCog
sumber
12
Daftar bagus! DBM tidak akan memeriksa konsistensi untuk bagian "R" dari CRUD, jadi saya akan mengambil bagian itu. Juga, ini mungkin merupakan pencucian karena di aplikasi Anda, Anda melakukan hal yang sama seperti yang dilakukan DBMS: Anda akan memeriksa dan memastikan ID induk valid sebelum CRD dan itu sebenarnya lebih lambat daripada meminta DBM melakukannya!
Matt Rogish
6
Bagaimana jika seseorang menghapus orang tua saat Anda memasukkan anak-anak? Saat ini ketika saya mengirim "tambahkan komentar" - jika Anda sudah menghapus jawaban Anda, komentar ini sekarang menjadi yatim piatu. FK akan mencegahnya. Juga, saya bisa mengubah parentID menjadi apapun yang saya inginkan. Seseorang harus memeriksanya. :)
Matt Rogish
7
Justru - itu harus menjadi pekerjaan DB, karena itu satu-satunya yang dapat menjamin transaksionalitas dalam menghadapi beberapa klien bersamaan.
SquareCog
3
+1 Jawaban luar biasa - alasan kedua untuk tidak menggunakan kendala FK dapat dianggap "mempersulit untuk mematahkan konsistensi" yang sebenarnya terdengar seperti hal yang baik !
Bill Karwin
9
Manfaat menggunakan kunci asing JAUH melebihi manfaat apa pun dari tidak menggunakannya menurut pendapat saya.
Nick Bedford
80

Ini adalah masalah pengasuhan. Jika di suatu tempat dalam karir pendidikan atau profesional Anda menghabiskan waktu untuk memberi makan dan merawat basis data (atau bekerja sama dengan orang-orang berbakat yang melakukannya), maka prinsip dasar entitas dan hubungan sudah tertanam dengan baik dalam proses pemikiran Anda. Di antara dasar-dasar itu adalah bagaimana / kapan / mengapa menentukan kunci dalam basis data Anda (primer, asing dan mungkin alternatif). Itu sifat kedua.

Namun, jika Anda belum memiliki pengalaman menyeluruh atau positif seperti itu di masa lalu dengan upaya terkait RDBMS, maka kemungkinan Anda tidak akan terpapar dengan informasi tersebut. Atau mungkin masa lalu Anda termasuk pencelupan dalam lingkungan yang sangat anti-database (misalnya, "para DBA itu idiot - kami sedikit, kami memilih beberapa kode java / c # slingers akan menyelamatkan hari"), dalam hal ini Anda mungkin akan sangat ditentang kepada ocehan aneh dari beberapa dweeb yang memberitahu Anda bahwa FK (dan kendala yang dapat mereka nyatakan) benar-benar penting jika Anda hanya mendengarkan.

Kebanyakan orang diajari ketika mereka masih anak-anak bahwa menyikat gigi itu penting. Bisakah Anda bertahan tanpa itu? Tentu, tetapi di suatu tempat di garis bawah Anda akan memiliki lebih sedikit gigi yang tersedia daripada yang bisa Anda miliki jika Anda menyikat setiap habis makan. Jika ibu dan ayah cukup bertanggung jawab untuk menutupi desain basis data dan juga kebersihan mulut, kita tidak akan melakukan percakapan ini. :-)

Ed Lucas
sumber
61
Saya akan menggunakan "kunci asing suling seperti menyikat gigi: maju, lakukan tanpanya, tapi hati-hati ketika Anda tersenyum"
Mark Sowul
5
Saya pribadi menemukan bahwa prinsip-prinsip RDBMS 'jauh lebih sederhana dan jauh lebih baik daripada kebersihan mulut
Ali Gangji
10 tahun ke depan, saya yakin akan memiliki desain database ini berbicara dengan putra / putri saya sehingga ia tidak mengacau dan akhirnya menjadi alasan untuk crash wall street berikutnya karena masalah database.
VarunAgw
52

Saya yakin ada banyak aplikasi yang bisa Anda gunakan, tetapi itu bukan ide terbaik. Anda tidak selalu dapat mengandalkan aplikasi Anda untuk mengelola database Anda dengan benar, dan mengelola database secara jujur ​​seharusnya tidak terlalu menjadi perhatian bagi aplikasi Anda.

Jika Anda menggunakan relasional database yang kemudian tampaknya Anda harus memiliki beberapa hubungan didefinisikan di dalamnya. Sayangnya sikap ini (Anda tidak perlu kunci asing) tampaknya dianut oleh banyak pengembang aplikasi yang lebih suka tidak diganggu dengan hal-hal konyol seperti integritas data (tetapi perlu karena perusahaan mereka tidak memiliki pengembang database khusus). Biasanya dalam database yang disatukan oleh tipe-tipe ini Anda beruntung hanya memiliki kunci primer;)

AlexCuse
sumber
26
Saya benar-benar tidak mendapatkan orang yang tidak memiliki FK di database mereka. Terakhir kali saya bekerja dengan seseorang yang tidak memilikinya, dia berkata "tidak, kami menerapkannya dalam aplikasi." Kecuali saya melakukan survei terhadap semua basis data pelanggan dan menemukan kebanyakan dari mereka memang memiliki anak yatim ...
ErikE
1
Itu biasanya tampaknya menjadi masalah. Saya pikir Anda bisa lolos dengan HANYA dalam database (selama pengguna Anda tidak keberatan dengan pengecualian runtime) tetapi memiliki keduanya adalah satu-satunya cara untuk melakukannya.
AlexCuse
Semuanya dalam transkrip / respons Atwood "Atwood: ... berdasarkan kunci asing yang Anda tetapkan dalam indeks, mereka mengetahuinya ... Spolsky: [tertawa] Dengan asumsi Anda melakukan itu. Atwood: Ya, dengan asumsi bahwa Anda mengatur basis data dengan benar ... "
MemeDeveloper
4
Basis data tidak disebut relasional karena hubungan antar tabel (SETIAP jenis database memiliki semacam hubungan antar entitas!), Tetapi karena tabel itu sendiri adalah hubungan , dalam istilah matematika. Lihat Wikipedia .
Massimiliano Kraus
41

Kunci asing penting untuk setiap model basis data relasional.

Belanda
sumber
54
Modelnya, ya. Implementasinya, tidak esensial, mungkin saja bermanfaat.
dkretz
4
Maaf, tetapi alasan utama mengapa pengembang aplikasi tidak menggunakan sistem manajemen basis data objek (alias database NoSQL!) Lebih luas adalah karena investasi dalam RDBMSs. Sebagian besar waktu database (bukan sistem manajemen basis data) adalah model objek tingkat menengah yang sering melibatkan cache terdistribusi. Di sinilah penghapusan cascading, kepemilikan, dan sinkronisasi perubahan harus terjadi. RDBMS digunakan terutama untuk kegigihan model objek ini, dan biasanya setelah latihan ORM yang sulit dan praktis tidak berharga. Model relasi seringkali tidak diperlukan!
Sentinel
2
tidak, kunci asing tidak wajib untuk menunjukkan "relasional"
Silver Moon
Ini tidak menjelaskan banyak hal.
Nae
29

Saya selalu menggunakannya, tetapi kemudian saya membuat database untuk sistem keuangan. Basis data adalah bagian penting dari aplikasi. Jika data dalam database keuangan tidak sepenuhnya akurat maka benar-benar tidak peduli berapa banyak usaha yang Anda lakukan dalam desain kode / front-end Anda. Anda hanya membuang-buang waktu saja.

Ada juga fakta bahwa banyak sistem umumnya perlu berinteraksi langsung dengan database - dari sistem lain yang baru saja membaca data (Crystal Reports) hingga sistem yang memasukkan data (tidak harus menggunakan API yang telah saya desain; mungkin ditulis oleh manajer bodoh yang baru saja menemukan VBScript dan memiliki kata sandi SA untuk kotak SQL). Jika basis data tidak sebodoh-idiot seperti itu, well-bye bye database.

Jika data Anda penting, maka ya, gunakan kunci asing, buat seperangkat prosedur tersimpan untuk berinteraksi dengan data, dan buat DB terberat yang Anda bisa. Jika data Anda tidak penting, mengapa Anda membuat database untuk memulai?

Semut
sumber
2
Wawasan yang bagus. Saya berpendapat bahwa data ini penting untuk setiap aplikasi yang benar-benar digunakan. Satu-satunya hal yang berbeda adalah konsekuensi dari data yang korup. Mereka tinggi untuk jenis aplikasi Anda ...
Jay Godse
20

Pembaruan : Saya selalu menggunakan kunci asing sekarang. Jawaban saya terhadap keberatan "pengujian mereka rumit" adalah "tulis pengujian unit Anda sehingga mereka tidak memerlukan database sama sekali. Setiap tes yang menggunakan database harus menggunakannya dengan benar, dan itu termasuk kunci asing. Jika pengaturannya menyakitkan, temukan cara yang tidak terlalu menyakitkan untuk melakukan pengaturan. "


Kunci asing mempersulit pengujian otomatis

Misalkan Anda menggunakan kunci asing. Anda sedang menulis tes otomatis yang mengatakan "ketika saya memperbarui akun keuangan, itu akan menyimpan catatan transaksi." Dalam tes ini, Anda hanya peduli dengan dua tabel: accountsdan transactions.

Namun, accountsmemiliki kunci asing untuk contracts, dan contractsmemiliki fk untuk clients, dan clientsmemiliki fk untuk cities, dan citiesmemiliki fk untuk states.

Sekarang database tidak akan memungkinkan Anda untuk menjalankan tes Anda tanpa mengatur data dalam empat tabel yang tidak terkait dengan tes Anda .

Setidaknya ada dua kemungkinan perspektif tentang ini:

  • "Itu hal yang baik: pengujian Anda harus realistis, dan kendala data itu akan ada dalam produksi."
  • "Itu hal yang buruk: kamu harus bisa menyatukan potongan-potongan uji sistem tanpa melibatkan potongan-potongan lain. Kamu bisa menambahkan tes integrasi untuk sistem secara keseluruhan."

Dimungkinkan juga untuk sementara menonaktifkan pemeriksaan kunci asing saat menjalankan tes. MySQL, setidaknya, mendukung ini .

Nathan Long
sumber
Saya menemukan diri saya biasanya pergi untuk jalan tengah di sini: Saya menggunakan FK, kemudian saya menulis metode unit-test helper yang mengatur DB untuk mendukung berbagai skenario pengujian, misalnya metode helper untuk mengisi "kota" dan "negara" untuk setiap tes yang membutuhkan tabel tersebut dihuni.
joelpt
Anda seharusnya menggunakan tabel tautan antara entitas yang tidak terkait mungkin. Atau melangkah lebih jauh - pisahkan DBS: pertimbangkan situasi dalam Arsitektur Berorientasi Layanan, atau Layanan Mikro, di mana setiap elemen (klien, akun, transaksi) adalah sistem yang berbeda, dengan DB yang berbeda. Tidak ada FK di antara mereka semua. Dalam hal ini, FK harus digunakan untuk mencegah data yatim dalam subtabel untuk setiap jenis data.
JeeBee
3
Ada juga DBMS yang memungkinkan kendala untuk ditangguhkan sehingga mereka hanya diperiksa ketika Anda melakukan seluruh transaksi, sehingga urutan memasukkan, memperbarui, menghapus tidak masalah
a_horse_with_no_name
2
Jika Anda menguji pembaruan dari lapisan bisnis, lingkungan pengembangan Anda harus memiliki FK. Ketika Anda memperbarui catatan Anda, Anda harus memiliki nilai kolom yang Anda butuhkan agar pembaruan berhasil. Kalau tidak, IMHO pengujian Anda tidak valid.
KeyOfJ
3
Basis data Anda bahkan tidak boleh terlibat dalam pengujian unit Anda, Anda harus mengejek mereka. Pada pengujian integrasi mereka akan terlibat tetapi masalah di sana karena kunci asing adalah sesuatu yang pengguna Anda juga akan mengalami kecuali Anda memperbaikinya.
Andreas Bergström
16

"Mereka dapat membuat menghapus catatan lebih rumit - Anda tidak dapat menghapus catatan" master "di mana ada catatan di tabel lain di mana kunci asing akan melanggar batasan itu."

Penting untuk diingat bahwa standar SQL mendefinisikan tindakan yang diambil ketika kunci asing dihapus atau diperbarui. Yang saya tahu adalah:

  • ON DELETE RESTRICT- Mencegah setiap baris di tabel lain yang memiliki kunci di kolom ini agar tidak dihapus. Inilah yang dijelaskan oleh Ken Ray di atas.
  • ON DELETE CASCADE - Jika baris di tabel lain dihapus, hapus baris apa pun dalam tabel ini yang merujuknya.
  • ON DELETE SET DEFAULT - Jika baris di tabel lain dihapus, atur kunci asing apa pun yang merujuknya ke default kolom.
  • ON DELETE SET NULL - Jika baris di tabel lain dihapus, atur kunci asing apa pun yang merujuknya dalam tabel ini ke nol.
  • ON DELETE NO ACTION- Kunci asing ini hanya menandakan bahwa itu adalah kunci asing; yaitu untuk digunakan dalam pemetaan ATAU.

Tindakan yang sama ini juga berlaku untuk ON UPDATE.

Default tampaknya tergantung pada mana server yang Anda gunakan.

Powerlord
sumber
14

@imphasing - inilah jenis pola pikir yang menyebabkan mimpi buruk pemeliharaan.

Mengapa oh mengapa Anda mengabaikan integritas referensial deklaratif, di mana data dapat dijamin setidaknya konsisten, mendukung apa yang disebut "penegakan perangkat lunak" yang merupakan langkah pencegahan yang lemah di terbaik.

Ed Guinness
sumber
Karena pengembang yang terlibat tidak pernah menangani masalah yang menuntut model relasional yang tidak sepele, dinormalisasi. Banyak masalah tidak, terutama yang banyak terdapat di pemrograman tipe web / "media sosial" yang sangat digemari saat ini. Jika apapun yang keluar dari kerangka ORM memenuhi masalah dalam alpha, tidak mungkin bagi siapa pun untuk berpikir lebih banyak tentang pemodelan data. Banyak masalah seperti itu dengan mudah ditangani oleh toko K / V, database dokumen atau serialisasi objek lurus.
zxq9
12

Ada satu alasan bagus untuk tidak menggunakannya: Jika Anda tidak mengerti peran mereka atau bagaimana menggunakannya.

Dalam situasi yang salah, kendala kunci asing dapat menyebabkan replikasi air terjun kecelakaan. Jika seseorang menghapus catatan yang salah, membatalkannya bisa menjadi tugas yang sangat besar.

Selain itu, sebaliknya, ketika Anda perlu menghapus sesuatu, jika dirancang dengan buruk, kendala dapat menyebabkan semua jenis kunci yang mencegah Anda.

Kent Fredric
sumber
8
Menghapus baris dalam produksi tanpa cadangan bukanlah argumen yang valid. Jika Anda tidak memahaminya, Anda harus mempertimbangkan untuk mempelajarinya alih-alih menghilangkannya.
Guillaume
2
@Guillaume Saya pikir jawabannya agak sarkastik, tidak bisa dipahami secara harfiah: jika Anda tidak memahaminya, maka jangan menggunakannya. Tapi tentu saja Anda berdua harus mengerti dan menggunakannya.
Benjamin
^ Ini. Mereka adalah alat yang berguna, tetapi di tangan seorang pemula, mereka adalah alat yang berbahaya.
Kent Fredric
11

Tidak ada alasan bagus untuk tidak menggunakannya ... kecuali jika baris yatim piatu bukan masalah besar bagimu.

Matt Rogish
sumber
11
Mengapa baris yatim merupakan masalah besar?
Seun Osewa
2
Bagaimana dengan multithreading? Mereka dapat menyebabkan mimpi buruk multithreading dalam situasi tertentu. Dalam aplikasi yang kompleks dengan beberapa utas menulis database yang mungkin menemukan objek yang perlu saling referensi, lebih baik untuk mengontrol integritas referensial dalam logika bisnis --- terutama jika tabel akan menjadi statis setelahnya.
Keith Pinson
Saya setuju. Juga, saya lebih suka memiliki baris ophan yang dapat saya pulihkan nanti, daripada membuangnya tanpa ampun.
PedroD
4

Pertanyaan yang lebih besar adalah: apakah Anda akan mengemudi dengan penutup mata? Begitulah jika Anda mengembangkan sistem tanpa kendala referensial. Perlu diingat, bahwa perubahan persyaratan bisnis, perubahan desain aplikasi, asumsi logis masing-masing dalam perubahan kode, logika itu sendiri dapat di-refactored, dan sebagainya. Secara umum, kendala dalam database ditempatkan di bawah asumsi logis kontemporer, yang tampaknya benar untuk serangkaian asumsi dan asumsi logis tertentu.

Melalui siklus hidup suatu aplikasi, referensi dan pemeriksaan data membatasi pengumpulan data polisi melalui aplikasi, terutama ketika persyaratan baru mendorong perubahan aplikasi logis.

Untuk subjek daftar ini - kunci asing tidak dengan sendirinya "meningkatkan kinerja", juga tidak "menurunkan kinerja" secara signifikan dari sudut pandang sistem pemrosesan transaksi real-time. Namun, ada biaya agregat untuk pemeriksaan kendala dalam sistem "batch" volume tinggi. Jadi, inilah perbedaan, proses transaksi real-time vs batch; pemrosesan batch - di mana biaya yang bertambah, yang ditimbulkan oleh cek kendala, dari batch yang diproses secara berurutan menimbulkan hit kinerja.

Dalam sistem yang dirancang dengan baik, pemeriksaan konsistensi data akan dilakukan "sebelum" memproses batch melalui (bagaimanapun, ada biaya yang terkait di sini juga); oleh karena itu, pemeriksaan batasan kunci asing tidak diperlukan selama waktu pengambilan. Faktanya semua kendala, termasuk kunci asing, harus dinonaktifkan untuk sementara hingga batch diproses.

KINERJA QUERY - jika tabel digabungkan dengan kunci asing, sadari fakta bahwa kolom kunci asing TIDAK DIINDEKSEKSI (meskipun kunci utama masing-masing diindeks berdasarkan definisi). Dengan mengindeks kunci asing, dalam hal ini, dengan mengindeks kunci apa pun, dan bergabung dengan tabel pada indeks membantu dengan kinerja yang lebih baik, bukan dengan bergabung pada kunci non-indeks dengan batasan kunci asing di atasnya.

Mengubah subjek , jika database hanya mendukung tampilan situs web / konten rendering / etc dan merekam klik, maka database dengan batasan penuh pada semua tabel adalah over kill untuk tujuan tersebut. Pikirkan tentang itu. Sebagian besar situs web bahkan tidak menggunakan database untuk itu. Untuk persyaratan yang serupa, di mana data hanya direkam dan tidak direferensikan per katakan, gunakan basis data dalam memori, yang tidak memiliki kendala. Ini tidak berarti bahwa tidak ada model data, ya model logis, tetapi tidak ada model data fisik.

jasbir L
sumber
Yah, saya tidak tahu mengapa memasukkan 3 baris baru ganda sebagai ganti baris kosong dan mengubah dua kata sama artinya dengan '67% adalah Jonathan Leffler ', tetapi saya tidak berpikir saya telah melakukan hal seperti itu. Teks utama disumbangkan oleh @jay (pengguna 183837).
Jonathan Leffler
Saya hanya berasumsi bahwa paragraf tidak akan berfungsi di sini seperti halnya di sebagian besar situs lain. Jadi, saya menempatkan semuanya sebagai satu, menggunakan huruf tebal untuk perubahan aliran.
jasbir L
3

Alasan Tambahan untuk menggunakan Kunci Asing: - Memungkinkan penggunaan kembali basis data yang lebih besar

Alasan Tambahan untuk TIDAK menggunakan Kunci Asing: - Anda mencoba mengunci pelanggan ke alat Anda dengan mengurangi penggunaan kembali.

Dan
sumber
3

Dari pengalaman saya selalu lebih baik untuk menghindari menggunakan FK dalam Aplikasi Basis Data Kritis. Saya tidak akan setuju dengan orang-orang di sini yang mengatakan FK adalah praktik yang baik tetapi tidak praktis di mana basis datanya sangat besar dan memiliki operasi CRUD yang besar / detik. Saya dapat berbagi tanpa menyebutkan ... salah satu bank investasi terbesar yang tidak memiliki FK tunggal dalam basis data. Kendala ini ditangani oleh programmer sambil membuat aplikasi yang melibatkan DB. Alasan dasarnya adalah ketika CRUD baru dilakukan, ia harus memengaruhi beberapa tabel dan memverifikasi untuk setiap sisipan / pembaruan, meskipun ini tidak akan menjadi masalah besar untuk kueri yang memengaruhi baris tunggal, tetapi itu membuat latensi besar ketika Anda berurusan dengan pemrosesan batch yang harus dilakukan bank besar sebagai tugas harian.

Lebih baik menghindari FK tetapi risikonya harus ditangani oleh programmer.

Rachit
sumber
8
Saya tidak berpikir praktik pembangunan di bank besar menetapkan standar emas.
Adriaan Koster
3

"Sebelum menambahkan catatan, periksa apakah catatan yang sesuai ada di tabel lain" adalah logika bisnis.

Berikut adalah beberapa alasan Anda tidak menginginkan ini dalam database:

  1. Jika aturan bisnis berubah, Anda harus mengubah database. Basis data perlu membuat ulang indeks dalam banyak kasus dan ini lambat pada tabel besar. (Mengubah aturan mencakup: izinkan tamu untuk mengirim pesan atau izinkan pengguna untuk menghapus akun mereka meskipun telah mengeposkan komentar, dll.).

  2. Mengubah database tidak semudah menggunakan perbaikan perangkat lunak dengan mendorong perubahan ke repositori produksi. Kami ingin menghindari mengubah struktur database sebanyak mungkin. Semakin banyak logika bisnis yang ada dalam database, semakin Anda meningkatkan kemungkinan perlu mengubah databae (dan memicu pengindeksan ulang).

  3. TDD. Dalam pengujian unit, Anda dapat mengganti basis data dengan tiruan dan menguji fungsionalitasnya. Jika Anda memiliki logika bisnis di database Anda, Anda tidak melakukan tes lengkap dan perlu menguji dengan database atau mereplikasi logika bisnis dalam kode untuk tujuan pengujian, menduplikasi logika dan meningkatkan kemungkinan logika tidak bekerja di database. cara yang sama.

  4. Menggunakan kembali logika Anda dengan sumber data yang berbeda. Jika tidak ada logika dalam database, aplikasi saya dapat membuat objek dari catatan dari database, membuat mereka dari layanan web, file json atau sumber lainnya. Saya hanya perlu menukar implementasi data mapper dan dapat menggunakan semua logika bisnis saya dengan sumber apa pun. Jika ada logika dalam database, ini tidak mungkin dan Anda harus menerapkan logika pada lapisan data mapper atau dalam logika bisnis. Either way, Anda memerlukan cek itu dalam kode Anda. Jika tidak ada logika dalam database saya bisa menggunakan aplikasi di lokasi yang berbeda menggunakan database yang berbeda atau implementasi flat-file.

Tom B
sumber
2

Saya setuju dengan jawaban sebelumnya yang berguna untuk menjaga konsistensi data. Namun, ada posting menarik oleh Jeff Atwood beberapa minggu yang lalu yang membahas pro dan kontra dari data yang dinormalisasi dan konsisten.

Dalam beberapa kata, basis data yang didenormalisasi dapat menjadi lebih cepat ketika menangani sejumlah besar data; dan Anda mungkin tidak peduli dengan konsistensi yang tepat tergantung pada aplikasi, tetapi itu memaksa Anda untuk lebih berhati-hati ketika berhadapan dengan data, karena DB tidak akan.

Santiago Palladino
sumber
Jeff membuat beberapa poin bagus. Namun, Dan Chak di "Enterprise Rails" menunjukkan cara untuk mendesain tabel cache yang pada dasarnya merupakan salinan data yang dinormalisasi. Kueri berjalan cepat, dan jika tabel tidak harus di-refresh, itu berfungsi dengan baik. Saya menemukan bahwa jika data Anda mendorong perilaku (misalnya keadaan aplikasi) dari aplikasi Anda, Anda perlu data dinormalisasi sebanyak mungkin karena jika tidak data yang tidak konsisten mengarah ke perilaku aplikasi yang tidak konsisten.
Jay Godse
Gudang data yang tidak normal dapat digunakan saat membaca volume data yang besar pada jalur akses yang konsisten dan diantisipasi . Dalam semua skenario lain, ini adalah kekeliruan yang berbahaya.
Peter Wone
2

Database Klarifikasi adalah contoh dari database komersial yang tidak memiliki kunci primer atau asing.

http://www.geekinterview.com/question_details/18869

Lucunya, dokumentasi teknis berusaha keras untuk menjelaskan bagaimana tabel terkait, kolom apa yang digunakan untuk bergabung dengan mereka dll.

Dengan kata lain, mereka bisa saja bergabung dengan tabel dengan deklarasi eksplisit (DRI) tetapi mereka memilih untuk tidak melakukannya .

Akibatnya, database Klarifikasi penuh dengan inkonsistensi dan kinerjanya buruk.

Tapi saya kira itu membuat pekerjaan pengembang lebih mudah, tidak harus menulis kode untuk berurusan dengan integritas referensial seperti memeriksa baris terkait sebelum menghapus, menambahkan.

Dan itu, saya pikir, adalah manfaat utama dari tidak memiliki batasan kunci asing dalam database relasional. Itu membuatnya lebih mudah untuk dikembangkan, setidaknya itu dari sudut pandang iblis-hati-hati.

Ed Guinness
sumber
Kode untuk menangani pemeriksaan integritas referensial yang gagal jauh lebih kecil daripada kode untuk menangani data yang tidak konsisten.
Jay Godse
@Jay setuju! Jangan pikir saya menganjurkan pendekatan ini.
Ed Guiness
2

Saya hanya tahu database Oracle, tidak ada yang lain, dan saya bisa mengatakan bahwa Foreign Key sangat penting untuk menjaga integritas data. Sebelum memasukkan data, struktur data perlu dibuat, dan dibuat benar. Ketika itu dilakukan - dan dengan demikian semua kunci utama DAN asing dibuat - pekerjaan selesai!

Artinya: baris yatim? Tidak. Tidak pernah melihat itu dalam hidupku. Kecuali jika programmer yang buruk lupa kunci asing, atau jika dia menerapkannya di tingkat lain. Keduanya - dalam konteks Oracle - kesalahan besar, yang akan menyebabkan duplikasi data, data anak yatim, dan dengan demikian: korupsi data. Saya tidak bisa membayangkan database tanpa FK ditegakkan. Sepertinya kekacauan bagi saya. Ini sedikit mirip dengan sistem izin Unix: bayangkan bahwa semua orang adalah root. Pikirkan kekacauan itu.

Kunci Asing sangat penting, seperti Kunci Utama. Itu seperti mengatakan: bagaimana jika kita menghapus Kunci Utama? Nah, kekacauan total akan terjadi. Itu apa. Anda mungkin tidak memindahkan tanggung jawab utama atau kunci asing ke tingkat pemrograman, itu harus di tingkat data.

Kekurangannya? Ya, tentu saja ! Karena saat dimasukkan, akan lebih banyak cek yang akan terjadi. Tetapi, jika integritas data lebih penting daripada kinerja, itu adalah no-brainer. Masalah dengan kinerja pada Oracle lebih terkait dengan indeks, yang datang dengan PK dan FK.

tvCa
sumber
1

Mereka dapat membuat menghapus catatan lebih rumit - Anda tidak dapat menghapus catatan "master" di mana ada catatan di tabel lain di mana kunci asing akan melanggar batasan itu. Anda bisa menggunakan pemicu untuk menghapus cascading.

Jika Anda memilih kunci utama secara tidak bijaksana, maka mengubah nilai itu menjadi lebih kompleks. Misalnya, jika saya memiliki PK dari tabel "pelanggan" saya sebagai nama orang tersebut, dan menjadikan kunci itu sebagai FK di tabel "pesanan", jika pelanggan ingin mengubah namanya, maka itu adalah masalah kerajaan. tapi itu hanya desain database yang jelek.

Saya percaya keuntungan menggunakan kunci fireign melebihi kerugian yang seharusnya.

Ken Ray
sumber
5
Saya cenderung jarang menghapus sesuatu. Tandai saja memiliki bit "Terlihat / aktif".
Dana
+1 untuk "Saya percaya keuntungan menggunakan kunci fireign melebihi kerugian apa pun yang seharusnya"
Ian Boyd
2
Anda tidak pernah mengubah nilai kunci utama. Anda menghapus seluruh baris dan membuatnya kembali secara berbeda. Jika Anda merasa perlu mengubahnya , skema Anda cacat.
DanMan
Mengubah nama pelanggan tidak akan merepotkan sama sekali JIKA kunci asing Anda ditetapkan pada CustomerId (PK). di tabel pesanan. Satu-satunya cara itu akan menyusahkan adalah jika FK ditetapkan pada CustomerName yang seharusnya tidak pernah terjadi. IMHO
KeyOfJ
1

Memverifikasi batasan kunci asing memerlukan waktu CPU, sehingga beberapa orang menghilangkan kunci asing untuk mendapatkan kinerja ekstra.

remonedo
sumber
6
Berapa banyak waktu CPU dihabiskan untuk menghapus data duplikat dan tidak konsisten?
Ed Guiness
Ya ini benar. Pada sistem yang saya kerjakan kita harus memasukkan 10 - 40 pertunjukan data sekaligus ke dalam basis data dan kinerja FK dengan dan tanpa terlihat dalam total waktu yang dibutuhkan.
Paul Mendoza
1

Saya telah mendengar argumen ini juga - dari orang-orang yang lupa untuk menempatkan indeks pada kunci asing mereka dan kemudian mengeluh bahwa operasi tertentu lambat (karena pengecekan kendala dapat memanfaatkan indeks apa pun). Jadi kesimpulannya: Tidak ada alasan bagus untuk tidak menggunakan kunci asing. Semua database modern mendukung penghapusan bertingkat, jadi ...

Arno
sumber
9
Saya percaya bahwa alasan sebenarnya kendala FK tidak digunakan oleh beberapa (sebagian besar, dari sudut pandang saya) adalah kemalasan semata-mata dengan alasan bahwa mereka dapat mempertahankan kemalasan mereka dengan argumen penghematan kinerja mereka. Saya sangat yakin bahwa sebagian besar Biaya Kebodohan yang ditimbulkan oleh perusahaan kami adalah karena kurangnya penegakan batasan-batasan FK dan efek riak yang ditimbulkannya melalui perusahaan. Kurangnya Unique Keys adalah hal lain yang membuat saya gila di sebelah 2.000 + prosedur tersimpan baris dengan 12 tingkat IF bersarang dan indentasi acak, tapi saya akan berhenti sekarang.
Chad
1

Argumen yang saya dengar adalah bahwa front-end harus memiliki aturan bisnis ini. Kunci asing "tambahkan overhead yang tidak perlu" ketika Anda seharusnya tidak membiarkan penyisipan apa pun yang melanggar kendala Anda sejak awal. Apakah saya setuju dengan ini? Tidak, tapi itulah yang selalu saya dengar.

EDIT: Dugaan saya adalah dia mengacu pada batasan kunci asing , bukan kunci asing sebagai konsep.

lordscarlet
sumber
Nggak. Dia tidak suka kunci yang sebenarnya!
ljs
Itu mengherankan saya. Ada perbedaan besar antara tidak menyukai batasan kunci asing dan tidak menyukai kunci asing. Saya tidak yakin bagaimana Anda memiliki basis data relasional tanpa mereka.
lordscarlet
Ya saya terkejut ketika saya mendengarnya. Namun dia mungkin secara tidak sengaja lidah; mungkin dia akan memposting di sini dan mengklarifikasi pada tahap tertentu :-)
ljs
1

Bagi saya, jika Anda ingin menggunakan standar ACID , sangat penting untuk memiliki kunci asing untuk memastikan integritas referensial.

CodeRot
sumber
1

Saya harus mengomentari sebagian besar komentar di sini, Foreign Key adalah item yang diperlukan untuk memastikan bahwa Anda memiliki data dengan integritas. Opsi berbeda untuk ON DELETE dan ON UPATE akan memungkinkan Anda untuk mengatasi beberapa "jatuh" yang disebutkan orang di sini mengenai penggunaannya.

Saya menemukan bahwa dalam 99% dari semua proyek saya, saya akan memiliki FK untuk menegakkan integritas data, namun, ada kesempatan langka di mana saya memiliki klien yang HARUS menyimpan data lama mereka, terlepas dari seberapa buruk itu .... tapi kemudian saya menghabiskan banyak waktu menulis kode yang masuk hanya untuk mendapatkan data yang valid pula, jadi itu menjadi sia-sia.

Penjual Mitchel
sumber
1

Bagaimana dengan pemeliharaan dan keteguhan di seluruh siklus hidup aplikasi? Sebagian besar data memiliki umur yang lebih panjang daripada aplikasi yang memanfaatkannya. Hubungan dan integritas data terlalu penting untuk dibiarkan dengan harapan bahwa tim pengembang selanjutnya akan memperbaikinya dalam kode aplikasi. Jika Anda belum bekerja pada db dengan data kotor yang tidak menghormati hubungan alami, Anda akan melakukannya. Pentingnya integritas data akan menjadi sangat jelas.


sumber
1

Saya juga berpikir bahwa kunci asing merupakan kebutuhan di sebagian besar basis data. Satu-satunya kelemahan (selain hit kinerja yang datang dengan memiliki konsistensi ditegakkan) adalah memiliki kunci asing memungkinkan orang untuk menulis kode yang mengasumsikan ada kunci asing fungsional. Itu seharusnya tidak pernah diizinkan.

Sebagai contoh, saya telah melihat orang-orang menulis kode yang memasukkan ke dalam tabel referensi dan kemudian mencoba memasukkan ke dalam tabel referensi tanpa memverifikasi bahwa sisipan pertama berhasil. Jika kunci asing dihapus di lain waktu, itu menghasilkan database yang tidak konsisten.

Anda juga tidak memiliki opsi untuk mengasumsikan perilaku tertentu saat memperbarui atau menghapus. Anda masih perlu menulis kode untuk melakukan apa yang Anda inginkan terlepas dari apakah ada hadiah kunci asing. Jika Anda menganggap penghapusan akan mengalir saat tidak, penghapusan Anda akan gagal. Jika Anda menganggap pembaruan untuk kolom yang dirujuk disebarkan ke baris referensi ketika tidak, pembaruan Anda akan gagal. Untuk keperluan penulisan kode, Anda mungkin juga tidak memiliki fitur-fitur itu.

Jika fitur-fitur tersebut dihidupkan, kode Anda akan tetap meniru mereka dan Anda akan kehilangan sedikit kinerja.

Jadi, rangkumannya .... Kunci asing sangat penting jika Anda memerlukan database yang konsisten. Kunci asing tidak boleh dianggap ada atau berfungsi dalam kode yang Anda tulis.

Eric
sumber
1

Saya menggemakan jawaban oleh Dmitriy - sangat bagus.

Bagi mereka yang khawatir tentang overhead kinerja yang sering dibawa oleh FK, ada cara (di Oracle) Anda bisa mendapatkan keuntungan optimizer query dari kendala FK tanpa biaya overhead validasi kendala selama memasukkan, menghapus atau memperbarui. Yaitu untuk membuat batasan FK dengan atribut RELY DISABLE NOVALIDATE. Ini berarti pengoptimal kueri MENANGGUNG bahwa kendala telah ditegakkan ketika membangun kueri, tanpa database yang benar-benar menegakkan kendala. Anda harus sangat berhati-hati di sini untuk mengambil tanggung jawab ketika Anda mengisi tabel dengan batasan FK seperti ini untuk memastikan Anda tidak memiliki data di kolom FK Anda yang melanggar batasan, seolah-olah Anda melakukannya, Anda bisa mendapatkan hasil yang tidak dapat diandalkan dari kueri yang melibatkan tabel kendala FK ini.

Saya biasanya menggunakan strategi ini pada beberapa tabel dalam skema data mart saya, tetapi tidak dalam skema pementasan terintegrasi saya. Saya memastikan tabel tempat saya menyalin data sudah memiliki batasan yang sama diberlakukan, atau ETL rutin memberlakukan kendala.

Mike McAllister
sumber
1

Banyak orang yang menjawab di sini terlalu terpaku pada pentingnya integritas referensial yang dilaksanakan melalui batasan referensial. Bekerja pada basis data besar dengan integritas referensial tidak berkinerja baik. Oracle tampaknya sangat buruk dalam penghapusan cascading. Aturan praktis saya adalah bahwa aplikasi tidak boleh memperbarui database secara langsung dan harus melalui prosedur tersimpan. Ini menjaga basis kode di dalam database, dan berarti bahwa database mempertahankan integritasnya.

Di mana banyak aplikasi mungkin mengakses database, masalah memang muncul karena kendala integritas referensial tetapi ini ke kontrol.

Ada masalah yang lebih luas juga dalam hal itu, pengembang aplikasi mungkin memiliki persyaratan yang sangat berbeda sehingga pengembang database mungkin tidak terlalu familiar.

Zak
sumber
5
"Aplikasi tidak boleh memperbarui database secara langsung dan harus melalui prosedur yang tersimpan. Ini menjaga basis kode di dalam database, dan berarti bahwa database mempertahankan integritasnya." <- Ada asumsi di sini bahwa logika dalam prosedur tersimpan tidak dapat melanggar integritas data, yang jelas-jelas salah.
Tim Gautier
1

Jika Anda benar-benar yakin, bahwa sistem basis data yang satu tidak akan berubah di masa mendatang, saya akan menggunakan kunci asing untuk memastikan integritas data.

Tapi di sini ada alasan kehidupan nyata yang sangat baik untuk tidak menggunakan kunci asing sama sekali:

Anda sedang mengembangkan produk, yang seharusnya mendukung sistem basis data yang berbeda.

Jika Anda bekerja dengan Entity Framework, yang dapat terhubung ke banyak sistem basis data yang berbeda, Anda mungkin juga ingin mendukung database tanpa server "open-source-free-of-charge". Tidak semua database ini dapat mendukung aturan kunci asing Anda (memperbarui, menghapus baris ...).

Ini dapat menyebabkan berbagai masalah:

1.) Anda mungkin mengalami kesalahan, ketika struktur database dibuat atau diperbarui. Mungkin hanya akan ada kesalahan diam, karena kunci asing Anda hanya diabaikan oleh sistem basis data.

2.) Jika Anda mengandalkan kunci asing, Anda mungkin akan membuat lebih sedikit atau bahkan tidak ada pemeriksaan integritas data dalam logika bisnis Anda. Sekarang, jika sistem database baru tidak mendukung aturan kunci asing ini atau hanya berperilaku dengan cara yang berbeda, Anda harus menulis ulang logika bisnis Anda.

Anda mungkin bertanya: Siapa yang butuh sistem basis data yang berbeda? Yah, tidak semua orang mampu atau menginginkan SQL-Server yang penuh sesak pada mesinnya. Ini adalah perangkat lunak, yang perlu dipertahankan. Yang lain sudah menginvestasikan waktu dan uang dalam beberapa sistem DB lainnya. Database tanpa server sangat bagus untuk pelanggan kecil di satu mesin.

Tidak ada yang tahu, bagaimana semua sistem DB ini berperilaku, tetapi logika bisnis Anda, dengan pemeriksaan integritas, selalu tetap sama.

Michael
sumber
0

Saya selalu berpikir itu malas untuk tidak menggunakannya. Saya diajari itu harus selalu dilakukan. Tetapi kemudian, saya tidak mendengarkan diskusi Joel. Dia mungkin punya alasan bagus, aku tidak tahu.

Kilhoffer
sumber
Itu lebih merupakan pernyataan spontan daripada diskusi, meskipun mungkin aku harus meneliti dengan tepat apa yang dia pikirkan tentang masalah ini secara mandiri! Namun saya juga ingin tahu tentang pendapat masyarakat tentang topik ini!
ljs
0

Satu kali ketika FK dapat menyebabkan Anda masalah adalah ketika Anda memiliki data historis yang merujuk kunci (dalam tabel pencarian) meskipun Anda tidak lagi ingin kunci tersedia.
Jelas solusinya adalah untuk merancang hal-hal yang lebih baik di muka, tetapi saya memikirkan situasi dunia nyata di sini di mana Anda tidak selalu memiliki kendali atas solusi lengkap. Setelah terbakar dengan ini beberapa kali Anda mungkin bersandar jauh dari penegakan hubungan. (Saya tidak mengatakan ini baik - hanya memberikan alasan mengapa Anda dapat memutuskan untuk menghindari FK dan db contraints secara umum)
Misalnya: mungkin Anda memiliki tabel pencarian customer_typeyang mencantumkan jenis pelanggan yang berbeda - katakanlah Anda harus menghapus jenis pelanggan tertentu, tetapi (karena hambatan bisnis) tidak dapat memperbarui perangkat lunak klien, dan tidak ada yang melihat situasi ini ketika mengembangkan perangkat lunak, fakta bahwa itu adalah kunci asing di beberapa tabel lain dapat mencegah Anda menghapus baris meskipun Anda tahu data historis yang merujuknya tidak relevan.

hamishmcn
sumber
Jika saya mengerti apa yang ingin Anda katakan, saya pikir jawaban saya adalah menghapus catatan secara logis di tabel pencarian atau mengarsipkan data historis yang tidak relevan lagi dan mengarsipkan catatan pencarian juga.
Chad