it-swarm-id.com

Apa yang salah dengan kunci asing?

Saya ingat pernah mendengar Joel Spolsky disebutkan di podcast 014 bahwa ia hampir tidak pernah 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)?

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

247
ljs

Alasan menggunakan Kunci Asing:

  • anda tidak akan mendapatkan Baris Yatim
  • anda bisa mendapatkan perilaku Nice "on delete cascade", 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 bekerja 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 kebanyakan 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.

344
SquareCog

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 yang 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 ocehan aneh dari beberapa dweeb memberi tahu 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. :-)

79
Ed Lucas

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 basis data relasional maka tampaknya Anda harus memiliki beberapa hubungan yang ditentukan 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;)

52
AlexCuse

Kunci asing penting ke model basis data relasional apa pun.

40
Galwegian

Saya selalu menggunakannya, tetapi kemudian saya membuat database untuk sistem keuangan. Basis data adalah bagian penting dari aplikasi. Jika data dalam basis data 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 SAuntuk kotak SQL). Jika basis datanya 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?

29
Ant

Pembaruan : Saya selalu menggunakan kunci asing sekarang. Jawaban saya untuk keberatan "pengujian mereka rumit" adalah "tulis tes 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: accounts dan transactions.

Namun, accounts memiliki kunci asing ke contracts, dan contracts memiliki fk ke clients, dan clients memiliki fk ke cities, dan cities memiliki fk ke 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 .

19
Nathan Long

"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 sebuah 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 sebuah 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 menandai bahwa itu adalah kunci asing; yaitu untuk digunakan dalam OR pemetaan.

Tindakan yang sama ini juga berlaku untuk ON UPDATE.

Defaultnya tampaknya bergantung pada server sql yang Anda gunakan.

14
Powerlord

@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.

14
Ed Guiness

Ada satu alasan bagus untuk tidak menggunakannya: Jika Anda tidak memahami peran mereka atau cara 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.

12
Kent Fredric

Tidak ada bagus alasan tidak untuk menggunakannya ... kecuali baris yatim piatu bukan masalah besar bagi Anda kurasa .

11
Matt Rogish

Pertanyaan yang lebih besar adalah: apakah Anda akan mengemudi dengan penutup mata? Begitulah jika Anda mengembangkan sistem tanpa batasan 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.

ntuk subjek listing 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 bertambah, yang ditimbulkan oleh pemeriksaan 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 sampai batch diproses.

QUERY PERFORMANCE - jika tabel digabung dengan kunci asing, sadari fakta bahwa kolom kunci asing TIDAK DIEKSEKSIMASI (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 basis data hanya mendukung tampilan situs web/merender konten/dll dan merekam klik, maka basis data dengan batasan penuh pada semua tabel dibasmi habis untuk keperluan 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.

4
jasbir L

Dari pengalaman saya selalu lebih baik untuk menghindari menggunakan FK dalam Aplikasi Basis Data Kritis. Saya tidak akan tidak setuju dengan orang-orang di sini yang mengatakan FK adalah praktik yang baik tetapi tidak praktis di mana database sangat besar dan memiliki operasi CRUD besar/detik. Saya dapat berbagi tanpa menyebutkan ... salah satu bank investasi terbesar yang tidak memiliki FK tunggal dalam basis data. Batasan 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.

3
Rachit

"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 menyebarkan 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 database untuk mengolok-olok dan menguji fungsionalitasnya. Jika Anda memiliki logika bisnis dalam 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 lain. 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 atau implementasi flat-file yang berbeda.

3
Tom B

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.

3
Dan

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

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

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 dapat bergabung dengan tabel dengan deklarasi eksplisit (DRI) tetapi mereka memilih untuk tidak .

Akibatnya, basis data Klarifikasi penuh dengan inkonsistensi dan berkinerja buruk.

Tapi saya kira itu membuat pekerjaan pengembang lebih mudah, tidak harus menulis kode untuk menangani 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.

2
Ed Guiness

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 mirip dengan sistem izin Unix: bayangkan bahwa semua orang adalah root. Pikirkan kekacauan.

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.

2
tvCa

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. Sebagai contoh, 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.

1
Ken Ray

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 UPDATE 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, jadi itu menjadi sia-sia.

1
Mitchel Sellers

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 merujuk ke batasan kunci asing , bukan kunci asing sebagai konsep.

1
lordscarlet

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

1
remonedo

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 bagus 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 masalah yang berbeda:

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 database.

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 basis data yang baru tidak mendukung aturan kunci asing ini atau hanya berlaku 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.

1
Michael

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.

1
Mike McAllister

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 cascade, jadi ...

1
Arno

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

1
CodeRot

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 bahwa pengembang database mungkin tidak terlalu familiar.

1
Zak

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.

Misalnya, 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.

1
Eric

Wowowo ...
Jawaban di mana-mana. Sebenarnya ini adalah topik paling rumit yang pernah saya temui. Saya menggunakan FK saat dibutuhkan tetapi di lingkungan produksi saya jarang menggunakannya.

Inilah mengapa saya jarang menggunakan Fks:

1. Sebagian besar waktu saya berurusan dengan data besar di server kecil untuk meningkatkan kinerja saya harus menghapus FK. Karena ketika Anda memiliki FK dan Anda membuat, Perbarui atau Hapus RDBMS pertama periksa apakah tidak ada pelanggaran kendala dan jika Anda memiliki DB besar yang bisa menjadi sesuatu yang fatal

2. Kadang-kadang saya perlu mengimpor data dari tempat lain dan karena saya tidak terlalu yakin seberapa baik mereka terstruktur, saya hanya membuang FK.

3. Jika Anda berurusan dengan banyak DB dan memiliki kunci referensi di DB lain tidak akan berjalan dengan baik (seperti untuk saat ini) sampai Anda menghapus FK (hubungan lintas basis data)
4. Mereka juga merupakan kasus ketika Anda menulis aplikasi yang akan duduk di RDBMS apa pun atau Anda ingin DB Anda diekspor dan diimpor dalam sistem RDBMS dalam hal ini setiap sistem RDBMS spesifik memiliki caranya sendiri dalam berurusan dengan FK dan Anda mungkin akan menjadi wajib untuk menghentikan penggunaan FK.

5. Jika Anda menggunakan platform RDBMS (ORM), Anda tahu bahwa beberapa dari mereka menawarkan pemetaan mereka sendiri tergantung pada solusi dan teknis tawaran mereka dan Anda tidak peduli tentang membuat tabel dan FK mereka.

6. Sebelum poin terakhir akan ada pengetahuan untuk berurusan dengan DB yang memiliki FK dan pengetahuan untuk menulis aplikasi yang melakukan semua pekerjaan tanpa perlu FK 7. Terakhir ketika saya mulai mengatakan itu semua tergantung pada skenario Anda, jika pengetahuan tidak sebuah pembatas. Anda akan selalu ingin menjalankan yang terbaik dari yang terbaik yang bisa Anda dapatkan!


Terima kasih semuanya!

Suatu saat 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, tapi saya berpikir tentang situasi dunia nyata di sini di mana Anda tidak selalu memiliki kendali atas solusi penuh.
Misalnya: mungkin Anda memiliki tabel pencarian _ customer_type yang mencantumkan jenis pelanggan yang berbeda - misalkan Anda perlu menghapus jenis pelanggan tertentu, tetapi (karena pembatasan bisnis) tidak dapat perbarui perangkat lunak klien, dan tidak ada yang menemukan 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.
Setelah terbakar dengan ini beberapa kali Anda mungkin condong menjauh dari penegakan hubungan.
(Saya tidak mengatakan ini baik - hanya memberikan alasan mengapa Anda dapat memutuskan untuk menghindari FK dan db contraints secara umum)

0
hamishmcn

Dalam sebuah proyek yang saya kerjakan sering kali ada hubungan implisit daripada hubungan eksplisit sehingga banyak tabel dapat digabungkan pada kolom yang sama.

Ambil tabel berikut

Alamat

  • AddressId (PK)
  • EntityId
  • Jenis Entitas
  • Kota
  • Negara
  • Negara
  • Dll ..

Nilai yang mungkin dari EntityType dapat berupa Karyawan, Perusahaan, Pelanggan, dan EntityId merujuk pada kunci utama dari tabel mana pun yang Anda minati.

Saya tidak benar-benar berpikir ini adalah cara terbaik untuk melakukan sesuatu, tetapi itu berhasil untuk proyek ini.

0
Curtis

Seperti banyak hal, ini merupakan tradeoff. Ini adalah pertanyaan tentang di mana Anda ingin melakukan pekerjaan untuk memverifikasi integritas data:

(1) menggunakan kunci asing (satu titik untuk mengkonfigurasi untuk tabel, fitur sudah diterapkan, diuji, terbukti berfungsi)

(2) serahkan ke pengguna basis data (kemungkinan banyak pengguna/aplikasi memperbarui tabel yang sama, yang berarti lebih banyak titik kegagalan potensial dan peningkatan kompleksitas dalam pengujian).

Ini lebih efisien untuk dilakukan oleh basis data (2), lebih mudah untuk mempertahankan dan mengurangi risiko dengan (1).

0
Jen A

Saya akan menggemakan apa yang dikatakan Dmitriy, tetapi menambahkan satu poin.

Saya bekerja pada sistem penagihan batch yang perlu memasukkan set besar baris di 30 + tabel. Kami tidak diizinkan melakukan pompa data (Oracle) sehingga kami harus melakukan sisipan massal. Meja-meja itu memiliki kunci asing, tetapi kami sudah memastikan bahwa mereka tidak memutuskan hubungan apa pun.

Sebelum menyisipkan, kami menonaktifkan batasan kunci asing sehingga Oracle tidak perlu selamanya melakukan sisipan. Setelah penyisipan berhasil, kami mengaktifkan kembali kendala.

NB: Dalam basis data besar dengan banyak kunci asing dan data baris anak untuk satu catatan, terkadang kunci asing bisa buruk, dan Anda mungkin ingin melarang penghapusan cascading. Bagi kami dalam sistem penagihan, itu akan memakan waktu terlalu lama dan terlalu membebani database jika kami melakukan penghapusan cascading, jadi kami hanya menandai catatan sebagai buruk dengan bidang pada tabel driver (induk) utama.

0
typicalrunt

Dalam DB2, jika MQT (Materialized Query Tables) digunakan, batasan kunci asing diperlukan untuk optimizer untuk memilih rencana yang tepat untuk setiap permintaan yang diberikan. Karena mengandung informasi kardinalitas, pengoptimal menggunakan metadata banyak untuk menggunakan MQT atau tidak.

0
Senthil

Salah satu prinsip yang baik dari desain struktur data adalah untuk memastikan bahwa setiap atribut tabel atau objek tunduk pada batasan yang dipahami dengan baik. Ini penting karena jika Anda atau program Anda dapat mengandalkan data yang valid di dalam basis data, kemungkinan besar Anda memiliki cacat program yang disebabkan oleh data yang buruk. Anda juga menghabiskan lebih sedikit waktu menulis kode untuk menangani kondisi kesalahan, dan Anda lebih cenderung menulis kode penanganan kesalahan di muka.

Dalam banyak kasus, kendala ini dapat didefinisikan pada waktu kompilasi, dalam hal ini Anda dapat menulis filter untuk memastikan bahwa atribut selalu berada dalam jangkauan, atau upaya untuk menyimpan atribut gagal.

Namun, dalam banyak kasus kendala ini dapat berubah pada saat run-time. Misalnya, Anda mungkin memiliki tabel "mobil" yang memiliki "warna" sebagai atribut yang awalnya mengambil nilai, misalnya, "merah", "hijau" dan "biru". Dimungkinkan selama pelaksanaan program untuk menambahkan warna yang valid ke daftar awal itu, dan "mobil" baru yang ditambahkan dapat mengambil warna apa pun dalam daftar warna terbaru. Selain itu, Anda biasanya ingin daftar warna yang diperbarui ini bertahan dari restart program.

Untuk menjawab pertanyaan Anda, ternyata jika Anda memiliki persyaratan untuk kendala data yang dapat berubah pada saat dijalankan, dan perubahan itu harus selamat dari restart program, kunci asing adalah solusi paling sederhana dan paling ringkas untuk masalah tersebut. Biaya pengembangan adalah penambahan satu tabel (mis. "Warna", batasan kunci asing ke tabel "mobil", dan indeks), dan biaya run-time adalah pencarian tabel tambahan untuk warna terkini. untuk memvalidasi data, dan biaya run-time ini biasanya dikurangi dengan pengindeksan dan caching.

Jika Anda tidak menggunakan kunci asing untuk persyaratan ini, Anda harus menulis perangkat lunak untuk mengelola daftar, mencari entri yang valid, menyimpannya ke disk, menyusun data secara efisien jika daftar besar, memastikan bahwa setiap pembaruan daftar tidak merusak file daftar, memberikan akses serial ke daftar jika ada banyak pembaca dan/atau penulis, dan sebagainya. mis. Anda perlu mengimplementasikan banyak fungsi RDBMS.

0
Jay Godse

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 yang bagus, saya tidak tahu.

0
Kilhoffer

Q uite sering kami menerima kesalahan dengan kendala FK Tidak dapat menambah atau memperbarui baris anak: batasan kunci asing gagal Misalkan ada dua tabel inventory_source dan contract_lines, dan kami merujuk inventory_source_id di contract_lines dari inventory_source dan misalkan kita ingin menghapus catatan dari inventory_source dan catatan sudah ada di contract_lines atau kita ingin menghapus kolom PK dari tabel Basis, kami mendapatkan kesalahan untuk kendala FK, kami bisa menghindarinya menggunakan langkah-langkah yang dituliskan di bawah ini.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

Kita dapat mengatasinya menggunakan langkah-langkah berikut: -

  1. Hapus atau perbarui baris dari inventory_source akan secara otomatis menghapus atau memperbarui baris yang cocok di tabel contract_lines dan ini dikenal sebagai cascade delete atau update.
  2. Cara lain untuk melakukannya adalah mengatur kolom i.e inventory_source_id di tabel contract_lines ke NULL, ketika catatan yang terkait dengannya dihapus di tabel inventory_source.
  3. Kita dapat membatasi tabel induk untuk menghapus atau memperbarui dengan kata lain kita dapat menolak operasi hapus atau perbarui untuk tabel inventory_source.
  4. Mencoba menghapus atau memperbarui nilai kunci utama tidak akan diizinkan untuk melanjutkan jika ada nilai kunci asing terkait di tabel yang direferensikan.
0
Vikas Kukreti