SQL - kunci utama tabel banyak-ke-banyak

125

Pertanyaan ini muncul setelah membaca komentar dalam pertanyaan ini:

Desain Basis Data

Saat Anda membuat tabel banyak-ke-banyak, jika Anda membuat kunci utama komposit pada dua kolom kunci asing, atau membuat kunci utama "ID" pengganti auto-increment, dan hanya meletakkan indeks pada dua kolom FK Anda (dan mungkin kendala unik)? Apa implikasi pada kinerja untuk memasukkan catatan baru / pengindeksan ulang di setiap kasus?

Pada dasarnya, ini:

PartDevice
----------
PartID (PK/FK)
DeviceID (PK/FK)

vs. ini:

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)

Pemberi komentar mengatakan:

membuat dua ID PK berarti tabel secara fisik diurutkan pada disk dalam urutan itu. Jadi jika kita memasukkan (Part1 / Device1), (Part1 / Device2), (Part2 / Device3), maka (Part 1 / Device3) database harus memecah tabel dan memasukkan yang terakhir antara entri 2 dan 3. Untuk banyak rekaman, ini menjadi sangat bermasalah karena melibatkan pengacakan ratusan, ribuan, atau jutaan rekaman setiap kali satu ditambahkan. Sebaliknya, PK yang mengalami peningkatan otomatis memungkinkan rekaman baru ditempelkan sampai akhir.

Alasan saya bertanya adalah karena saya selalu cenderung melakukan kunci utama komposit tanpa kolom kenaikan otomatis pengganti, tetapi saya tidak yakin apakah kunci pengganti sebenarnya lebih berkinerja.

Andy White
sumber
Berikut pertanyaan silimar yang diposting di SO: stackoverflow.com/questions/344068/…
Tony
(Mencoba menambahkan ini ke komentar saya sebelumnya tetapi tidak bisa) Bergantung pada jumlah sisipan Anda juga dapat secara berkala membangun kembali indeks Anda untuk memastikan hasilnya dengan cepat. Di SQL Server, Anda juga dapat mengubah FILLFACTOR indeks untuk menyediakan ruang yang cukup untuk penyisipan sebelum harus memindahkan data.
Tony
1
Bukankah jawabannya bergantung pada DBMS yang digunakan? Saya menduga MySQL akan berperilaku dalam kasus ini, SQL-Server sedikit berbeda, dll.
Radu Murzea
Peringatan: Tanpa tag database tertentu, banyak hal yang dikatakan di sini mencurigakan. Mesin yang berbeda bekerja secara berbeda!
Rick James

Jawaban:

85

Dengan pemetaan banyak-ke-banyak dua kolom yang sederhana, saya melihat tidak ada keuntungan nyata memiliki kunci pengganti. Memiliki kunci utama pada (col1,col2)dijamin unik (dengan asumsi nilai col1dan Anda col2dalam tabel yang direferensikan unik) dan indeks terpisah pada (col2,col1)akan menangkap kasus-kasus di mana urutan sebaliknya akan dieksekusi lebih cepat. Pengganti adalah pemborosan ruang.

Anda tidak perlu indeks pada kolom individual karena tabel hanya boleh digunakan untuk menggabungkan dua tabel yang direferensikan bersama.

Komentar yang Anda maksud dalam pertanyaan tidak sebanding dengan elektron yang digunakannya, menurut pendapat saya. Sepertinya penulis menganggap tabel disimpan dalam array daripada struktur pohon multi-arah yang seimbang dengan kinerja yang sangat tinggi.

Sebagai permulaan, tidak perlu menyimpan atau mendapatkan tabel yang diurutkan, cukup indeksnya. Dan indeks tidak akan disimpan secara berurutan, itu akan disimpan dengan cara yang efisien agar dapat diambil dengan cepat.

Selain itu, sebagian besar tabel database jauh lebih sering dibaca daripada ditulis. Itu membuat apa pun yang Anda lakukan di sisi pilih jauh lebih relevan daripada apa pun di sisi sisipan.

paxdiablo
sumber
Poin terakhir bukanlah generalisasi yang baik: "sebagian besar tabel database dibaca jauh lebih sering daripada yang tertulis". Saya menemukan banyak contoh tabel asosiatif yang perlu sering ditulis, misalnya tabel yang menghubungkan pelanggan dengan pesanan.
pengguna
5
@ Buffer, saya akan mendukung komentar itu (secara teknis, ini adalah generalisasi hanya jika saya mengatakan "semua tabel", "sebagian besar" didasarkan pada pengalaman). Mari kita pikirkan juga contoh Anda, pesanan dibuat sekali (mungkin kadang-kadang diperbarui tetapi itu tidak mungkin mengubah info kunci / indeks, lebih untuk mengenai hal-hal seperti status pesanan. Namun, pembaruan dan pilihan yang perlu Anda lakukan untuk mencetak faktur atau menghasilkan laporan manajemen akan melebihi sisipan aslinya.
paxdiablo
Pikirkan Amazon - Ribuan pesanan dibuat setiap jam.
pengguna
9
@buffer, ya, tapi sekali lagi, masing-masing perintah akan hampir pasti akan bertanya berkali-kali untuk melakukan (misalnya) kemasan, penagihan, update status, analisis bisnis dan sebagainya. Jumlah absolut kreasi kurang penting dibandingkan rasio antara kreasi dan pembacaan.
paxdiablo
1
Maksud saya adalah, insertakan menjadi masalah jika dilakukan ribuan kali per jam. Anda tidak bisa mengabaikannya begitu saja hanya karena rasio insertto selectadalah <1. Dalam hal ini, pelanggan peduli tentang berapa banyak waktu yang dibutuhkan untuk melakukan pemesanan.
pengguna
19

Tidak ada kunci pengganti yang diperlukan untuk tabel tautan.

Satu PK di (col1, col2) dan indeks unik lainnya di (col2, col1) adalah semua yang Anda butuhkan

Kecuali Anda menggunakan ORM yang tidak dapat mengatasi dan menentukan desain DB Anda untuk Anda ...

Edit: Saya menjawab hal yang sama di sini: SQL: Apakah Anda memerlukan kunci primer inkremental otomatis untuk tabel Banyak-Banyak?

gbn
sumber
3
Anda mungkin baik-baik saja dengan indeks dups pada col2 daripada indeks unik pada (col2, col1). Keuntungan dari indeks dua kolom adalah memungkinkan pemindaian hanya indeks pada col2 saja atau pada col1 dan col2 (meskipun indeks lain, on (col1, col2) juga menangani kasus 'keduanya'). Sisi negatifnya adalah penyimpanan ekstra yang dibutuhkan untuk kolom tambahan. Ini biasanya tidak signifikan, jadi sarannya jauh dari kata buruk. Namun demikian, jika col1 dan col2 besar atau sangat berbeda ukurannya, Anda dapat menghemat ruang tanpa mengganggu kinerja dengan memilih indeks kedua hanya pada kolom yang lebih pendek.
Jonathan Leffler
@gbn: Indeks kedua pada (col2, col1) tidak harus unik, bukan?
pengguna
1
menempatkan indeks unik pada (col1, col2) setelah itu sudah merupakan PK sepenuhnya berlebihan
Don Cheadle
@mmcrae: dimana kita melakukan itu?
gbn
2
@mmcrae: Komentar Anda adalah "meletakkan indeks unik pada (col1, col2) ..". Urutan kolom dalam indeks penting. (col2, col1)tidak (col1, col2). PK dari (col1, col2)mungkin tidak cocok untuk semua kueri dan menghasilkan pemindaian, jadi memiliki kebalikannya meningkatkan kinerja karena memungkinkan pencarian di mana col2 lebih baik. Misalnya, validasi FK ketika tabel dengan col2 memiliki penghapusan. Meja anak smuts diperiksa
gbn
12

Kunci utama inkremental mungkin diperlukan jika tabel direferensikan. Mungkin ada detail dalam tabel banyak ke banyak yang perlu ditarik dari tabel lain menggunakan kunci primer inkremental.

sebagai contoh

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Other Details

Sangat mudah untuk menarik 'Detail Lainnya' menggunakan PartDevice.ID sebagai FK. Oleh karena itu penggunaan kunci primer inkremental diperlukan.

Jronny
sumber
1
Terima kasih! Saya sampai pada jawabannya karena saya mencari skenario yang hampir sama dengan yang Anda gambarkan. Tapi Anda menjauh dari kalimat pertama Anda dengan menambahkan "Detail lainnya". Bagaimana jika saya memiliki banyak tabel pemetaan, yang perlu saya rujuk dari tabel lain? Artinya, tabel pemetaan banyak ke banyak belum menyimpan informasi lain ... Apakah kolom ID tambahan tetap masuk akal? Jika tidak, bagaimana cara merujuk ke satu catatan tabel pemetaan?
misanthrop
Ada dua opsi di sini, Anda dapat menggunakan kunci gabungan sebagai kunci asing dari tabel referensi Anda (ini menambahkan kolom tambahan ke tabel baru Anda), atau Anda dapat membuat kolom id ke tabel pemetaan dan menetapkan batasan unik ke gabungan asli kunci utama sedangkan kolom id baru akan menjadi kunci utama.
Vočko
6

Cara terpendek dan paling langsung saya dapat menjawab pertanyaan Anda adalah dengan mengatakan bahwa akan ada dampak kinerja jika dua tabel yang Anda tautkan tidak memiliki kunci primer berurutan. Seperti yang Anda nyatakan / kutip, indeks untuk tabel tautan akan menjadi terfragmentasi, atau DBMS akan bekerja lebih keras untuk menyisipkan rekaman jika tabel tautan tidak memiliki kunci primer berurutannya sendiri. Inilah alasan kebanyakan orang meletakkan kunci utama yang bertambah secara berurutan pada tabel tautan.

Bernhard Hofmann
sumber
2

Jadi sepertinya jika tugas HANYA adalah menghubungkan dua tabel, PK terbaik adalah PK kolom ganda.

Tetapi jika itu melayani tujuan lain, tambahkan NDX lain sebagai PK dengan kunci asing dan indeks unik kedua.

Indeks atau PK adalah cara terbaik untuk memastikan tidak ada duplikat. PK memungkinkan alat seperti Microsoft Management Studio melakukan beberapa pekerjaan (membuat tampilan) untuk Anda

michael kosak
sumber