Apakah kunci asing secara otomatis membuat indeks?

389

Saya telah diberitahu bahwa jika saya kunci asing dua tabel, SQL Server akan membuat sesuatu yang mirip dengan indeks di tabel anak. Saya kesulitan mempercayai ini benar, tetapi tidak bisa menemukan banyak di luar sana yang terkait dengan ini.

Alasan sebenarnya saya menanyakan hal ini adalah karena kami mengalami waktu respons yang sangat lambat dalam pernyataan penghapusan terhadap tabel yang mungkin memiliki 15 tabel terkait. Saya telah bertanya kepada orang basis data kami dan dia mengatakan bahwa jika ada kunci asing di ladang, maka itu bertindak seperti indeks. Apa pengalaman Anda dengan ini? Haruskah saya menambahkan indeks pada semua bidang kunci asing atau hanya overhead yang tidak perlu?

Nick DeVore
sumber
Saya memiliki pemahaman yang sama dengan orang DB Anda - bahwa FK sebenarnya membuat indeks.
Vinnie
9
Tidak - FK TIDAK secara otomatis membuat indeks. Masuk akal untuk membuatnya - tetapi TIDAK dilakukan secara otomatis oleh SQL Server.
marc_s
47
tidak konyol untuk menanyakan ini sama sekali!
marc_s
5
Jika Anda mendapatkan penghapusan lambat dan tabel yang Anda hapus dari direferensikan oleh tabel lain, Anda mungkin akan mendapatkan peningkatan kinerja dengan mengindeks kunci asing di tabel lainnya . Ini karena ketika SQL menghapus sebuah baris, ia perlu memeriksa integritas referensial pada baris tersebut. Untuk melakukan ini, jelas perlu memeriksa bahwa tidak ada baris lain yang mereferensikan baris yang Anda hapus.
Noel Kennedy
3
Saya akan mengatakan seorang pangkalan data orang yang tidak tahu ini harus sangat membutuhkan pelatihan. Database orang bertanggung jawab atas kinerja, itu tugas mereka untuk mengetahui hal semacam ini. Ini menunjukkan ketidakmampuan kotor.
HLGEM

Jawaban:

343

Kunci asing adalah kendala, hubungan antara dua tabel - yang tidak ada hubungannya dengan indeks per se.

Tetapi ini adalah fakta yang diketahui bahwa sangat masuk akal untuk mengindeks semua kolom yang merupakan bagian dari hubungan kunci asing, karena melalui hubungan FK, Anda akan sering perlu mencari tabel terkait dan mengekstrak baris tertentu berdasarkan nilai tunggal atau rentang nilai.

Jadi masuk akal untuk mengindeks setiap kolom yang terlibat dalam FK, tetapi FK per se bukanlah indeks.

Lihat artikel hebat Kimberly Tripp "Kapan SQL Server berhenti meletakkan indeks pada kolom Kunci Asing?" .

marc_s
sumber
Ya. Saya hampir positif bahwa PostgreSQL membuat indeks. Saya cukup yakin MySQL melakukannya. Membuat indeks masuk akal, tetapi TIDAK DIBUTUHKAN. Lagi pula, mengapa referensi sesuatu jika setiap kali DB pergi untuk mencarinya itu harus melakukan tablescan?
MBCook
Artikel yang disebutkan di atas agak membingungkan karena SQL server atau database lain tidak pernah menempatkan indeks pada FK.
vsingh
7
@vsingh: itulah yang ingin disampaikan oleh artikel - ini adalah kesalahpahaman umum bahwa FK secara otomatis membuat indeks - tidak melakukan itu.
marc_s
5
@MBCook Tidak, PostgreSQL tidak (setidaknya dalam versi 9.2 atau versi sebelumnya) secara otomatis membuat indeks pada sisi referensi dari hubungan kunci asing yang ditentukan dengan REFERENCES. Secara otomatis membuat UNIQUEindeks untuk suatu PRIMARY KEYatau UNIQUEkendala, dan mengharuskan UNIQUEindeks hadir untuk akhir yang dirujuk dari hubungan kunci asing, tetapi tidak melakukan apa pun secara otomatis untuk akhir referensi , meskipun sering kali merupakan ide yang baik untuk membuatnya sendiri. Lihat stackoverflow.com/questions/970562/…
Craig Ringer
16
Kebingungan mungkin ada karena MySQL InnoDB keduanya membutuhkan dan secara otomatis membuat indeks ketika Anda menambahkan kunci asing - dev.mysql.com/doc/refman/5.5/en/…
humbads
42

Wow, jawabannya ada di peta. Jadi Dokumentasi mengatakan:

Batasan KUNCI ASING adalah kandidat untuk indeks karena:

  • Perubahan batasan PRIMARY KEY diperiksa dengan batasan FOREIGN KEY di tabel terkait.

  • Kolom kunci asing sering digunakan dalam kriteria gabungan ketika data dari tabel terkait digabungkan dalam kueri dengan mencocokkan kolom dalam batasan ASING dari satu tabel dengan kolom kunci utama atau unik di tabel lain. Indeks memungkinkan Microsoft® SQL Server ™ 2000 untuk menemukan data terkait dalam tabel kunci asing dengan cepat. Namun, membuat indeks ini bukan keharusan. Data dari dua tabel terkait dapat digabungkan bahkan jika tidak ada batasan PRIMARY KEY atau FOREIGN KEY yang didefinisikan di antara tabel, tetapi hubungan kunci asing antara dua tabel menunjukkan bahwa dua tabel telah dioptimalkan untuk digabungkan dalam permintaan yang menggunakan kunci sebagai kriterianya.

Jadi sepertinya cukup jelas (walaupun dokumentasinya agak kacau) bahwa sebenarnya tidak membuat indeks.

Yishai
sumber
5
Tepat - ini adalah CALON untuk indeks - tetapi tidak secara otomatis dibuat sebagai indeks! Cukup jelas sebenarnya, IMHO :-)
marc_s
4
Saya menemukan bagian ini kacau: "hubungan kunci asing antara dua tabel menunjukkan bahwa dua tabel telah dioptimalkan untuk digabungkan dalam permintaan yang menggunakan kunci sebagai kriteria." Itu seharusnya berbunyi "... dua tabel harus dioptimalkan ..."
Yishai
18

Tidak, tidak ada indeks implisit pada bidang kunci asing, jika tidak mengapa Microsoft mengatakan "Membuat indeks pada kunci asing sering berguna" . Kolega Anda mungkin membingungkan bidang kunci asing di tabel referensi dengan kunci utama di tabel yang dirujuk ke - kunci utama memang membuat indeks implisit.

Michael Borgwardt
sumber
apa itu "Indeks implisit"? apakah itu hanya menyiratkan bahwa ada ab * tree tanpa membuatnya?
Stephanie Page
1
@Stephanie Page: Ini adalah ekspresi yang baru saja saya buat untuk jawaban ini yang berarti indeks yang dibuat secara otomatis. Jika Anda mendeklarasikan kunci utama, SQL server secara otomatis membuat dan mengindeksnya. Tetapi tidak jika Anda mendeklarasikan kunci asing (beberapa sistem DB lainnya melakukannya).
Michael Borgwardt
7

SQL Server membuat otomatis indeks untuk Kunci Utama, tetapi tidak untuk Kunci Asing. Buat indeks untuk Kunci Asing. Mungkin bernilai overhead.

Paul Sonier
sumber
6

Katakanlah Anda memiliki meja besar yang disebut pesanan, dan meja kecil yang disebut pelanggan. Ada kunci asing dari pesanan ke pelanggan. Sekarang jika Anda menghapus pelanggan, Sql Server harus memeriksa bahwa tidak ada pesanan anak yatim; jika ada, itu menimbulkan kesalahan.

Untuk memeriksa apakah ada pesanan, Sql Server harus mencari tabel pesanan besar. Sekarang jika ada indeks, pencarian akan cepat; jika tidak, pencarian akan lambat.

Jadi dalam hal ini, penghapusan lambat bisa dijelaskan dengan tidak adanya indeks. Apalagi jika Sql Server harus mencari 15 tabel besar tanpa indeks.

NB. Jika kunci asing memiliki HAPUS HAPUS CASCADE, Sql Server masih harus mencari tabel pesanan, tetapi kemudian untuk menghapus perintah yang merujuk pelanggan yang dihapus.

Andomar
sumber
Tepat - itulah alasan indeks pada FK memang membuat banyak akal (sebagian besar waktu)
marc_s
1
Sebagian besar waktu? Sepertinya ini adalah kasus untuk menghapus dari orangtua. Jika sebagian besar waktu Anda menghapus dari orang tua, saya kira itu benar.
Stephanie Page
6

Kunci asing tidak membuat indeks. Hanya batasan kunci alternatif (UNIK) dan batasan kunci primer yang membuat indeks. Ini berlaku di Oracle dan SQL Server.

Sandeep Kanuri
sumber
3

Tidak sepengetahuan saya. Kunci asing hanya menambahkan batasan bahwa nilai dalam kunci anak juga diwakili di suatu tempat di kolom induk. Itu tidak memberi tahu database bahwa kunci anak juga perlu diindeks, hanya dibatasi.

Gandalf
sumber
3

Sebenarnya, kunci asing sama sekali tidak ada hubungannya dengan indeks, ya. Tapi, seperti yang ditunjukkan oleh pembicara di atas, masuk akal untuk membuat satu untuk mempercepat pencarian FK. Bahkan, di MySQL, jika Anda tidak menentukan indeks dalam deklarasi FK Anda, mesin (InnoDB) membuatnya untuk Anda secara otomatis.

shylent
sumber
3

Di PostgeSql Anda dapat memeriksa indeks sendiri jika Anda menekan \ nama tab

Anda akan melihat bahwa indeks btree telah secara otomatis dibuat pada kolom dengan kunci primer dan batasan unik, tetapi tidak pada kolom dengan kunci asing.

Saya pikir itu menjawab pertanyaan Anda setidaknya untuk postgres.

Gregor
sumber
Maaf, saya tidak melihat bahwa pertanyaannya menyangkut MS SQL Server tetapi setelah mengirim jawabannya. Mungkin masih bisa membantu seseorang ...
Gregor
2

Saya perhatikan bahwa Entity Framework 6.1 menunjuk pada MSSQL tidak secara otomatis menambahkan indeks pada kunci asing.

Luke Puplett
sumber
Saya tidak percaya itu terjadi jika Anda menandai kolom secara manual sebagai bagian dari indeks (misalnya jika Anda membuat indeks komposit lebih dari beberapa anggota)
Rowland Shaw
0

InnoDB membutuhkan indeks pada kunci asing dan kunci referensi sehingga pemeriksaan kunci asing dapat cepat dan tidak memerlukan pemindaian tabel. Dalam tabel referensi, harus ada indeks di mana kolom kunci asing terdaftar sebagai kolom pertama dalam urutan yang sama.

Talha F.
sumber