Apakah saya perlu membuat indeks pada kunci asing di Oracle?

120

Saya memiliki meja Adan mejaB . Amemiliki kunci asing untuk Bdi B's kunci utama, B_ID.

Untuk beberapa alasan (saya tahu ada alasan yang sah) tidak menggunakan indeks ketika saya menggabungkan kedua tabel ini pada tombol.

Apakah saya perlu membuat indeks secara terpisah di A.B_ID atau haruskah keberadaan kunci asing menyediakannya?

aw crud
sumber

Jawaban:

137

Batasan kunci asing saja tidak menyediakan indeks pada Oracle - harus (dan harus) dibuat.

DCookie
sumber
11
Pada beberapa database, membuat batasan kunci asing juga membuat indeks ... yaitu Jet Engine (file MSAccess, Firebird dan MySQL)
bubi
17
Jawaban ini tidak ada artinya tanpa secara eksplisit mengacu pada implementasi database tertentu. Tentu pertanyaannya diberi tag oracletetapi itu tidak segera jelas ketika Anda mendarat di sini dari pencarian google.
developerbmw
5
Saya dapat mengonfirmasi bahwa PostgreSQL - setidaknya pada saat posting ini - tidak melakukannya secara otomatis.
The Dembinski
Jawaban yang sama untuk SQL Server (2016, Azure ...), sejauh yang saya tahu.
Pac0
Mengapa seseorang harus membuat indeks pada kunci asing dengan Oracle? Apa konsekuensi dari tidak melakukannya?
Đỗ Công Bằng
46

Membuat kunci asing tidak secara otomatis membuat indeks pada A.B_ID. Jadi secara umum masuk akal dari perspektif kinerja kueri untuk membuat indeks terpisah pada A.B_ID.

Jika Anda pernah menghapus baris di B, Anda pasti ingin A.B_ID diindeks. Jika tidak, Oracle harus melakukan pemindaian tabel lengkap pada A setiap kali Anda menghapus baris dari B untuk memastikan bahwa tidak ada rekaman yatim piatu (tergantung pada versi Oracle, mungkin ada implikasi penguncian tambahan juga, tetapi itu berkurang dalam versi Oracle yang lebih baru).

Gua Justin
sumber
1
Bagaimana dengan kolom PFK? misalnya jika saya memiliki tabel perantara untuk hubungan banyak-ke-banyak, sholud saya membuat indeks untuk dua kolom PFK dari tabel ini?
Clamari
3
@Clamari - Jika C memiliki kunci utama (A_ID, B_ID), kunci utama akan menjaga agar dapat menghapus dari A. Jika Anda juga ingin dapat menghapus dari B secara efisien, Anda ingin indeks aktif B_ID.
Gua Justin
25

Hanya untuk info lebih lanjut: Oracle tidak membuat indeks secara otomatis (seperti yang dilakukannya untuk batasan unik) karena (a) tidak diperlukan untuk memaksakan batasan, dan (b) dalam beberapa kasus Anda tidak memerlukannya.

Paling besar waktu, namun Anda akan ingin membuat indeks (pada kenyataannya, di Oracle Apex ada laporan dari "kunci asing unindexed").

Setiap kali aplikasi perlu menghapus baris dalam tabel induk, atau memperbarui nilai PK (yang lebih jarang), DML akan menderita jika tidak ada indeks, karena harus mengunci seluruh tabel anak.

Kasus di mana saya biasanya memilih untuk tidak menambahkan indeks adalah di mana FK berada ke tabel "data statis" yang mendefinisikan domain kolom (misalnya tabel kode status), di mana pembaruan dan penghapusan pada tabel induk tidak pernah dilakukan langsung oleh aplikasi. Namun, jika menambahkan indeks pada kolom memberi manfaat pada kueri penting dalam aplikasi, maka indeks akan tetap menjadi ide yang bagus.

Jeffrey Kemp
sumber
14

SQL Server tidak pernah memasukkan indeks ke kolom kunci asing secara otomatis - lihat postingan blog Kim Tripp yang sangat bagus tentang latar belakang dan sejarah mitos urban ini.

Biasanya merupakan ide bagus untuk mengindeks kolom kunci asing Anda, bagaimanapun - jadi ya, saya akan merekomendasikan untuk memastikan setiap kolom FK didukung oleh indeks; tidak harus hanya pada satu kolom itu saja - mungkin masuk akal untuk membuat indeks pada dua atau tiga kolom dengan kolom FK sebagai yang pertama di sana. Tergantung pada skenario dan data Anda.

marc_s
sumber
8

Untuk alasan kinerja, indeks harus dibuat. Digunakan dalam operasi hapus pada tabel utama (untuk memeriksa bahwa catatan yang Anda hapus tidak digunakan) dan dalam gabungan yang biasanya melibatkan kunci asing. Hanya beberapa tabel (saya tidak membuatnya dalam log) yang mungkin tidak memerlukan indeks tetapi mungkin, dalam kasus ini mungkin Anda tidak memerlukan batasan kunci asing juga.

TAPI

Ada beberapa database yang sudah otomatis membuat indeks pada kunci asing. Jet Engine (Microsoft Access Files) Firebird MySQL

TENTUNYA

SQL Server Oracle

TIDAK

bubi
sumber
3
Thx untuk menyebutkan bahwa FIrebird SQL melakukannya secara otomatis. Tepat seperti itulah yang saya cari.
pengguna424855
1

Seperti apapun yang berhubungan dengan kinerja, itu tergantung pada banyak faktor dan tidak ada peluru silve misalnya dalam lingkungan aktivitas yang sangat tinggi pemeliharaan indeks mungkin tidak dapat diterima.

Yang paling menonjol di sini tampaknya adalah selektivitas: jika nilai dalam indeks akan sangat diduplikasi maka akan memberikan kinerja yang lebih baik untuk menghapus indeks (jika mungkin) dan memungkinkan pemindaian tabel.

onedaywhen
sumber
1

Batasan UNIQUE, PRIMARY KEY, dan FOREIGN KEY menghasilkan indeks yang memberlakukan atau "mendukung" batasan (dan terkadang disebut indeks dukungan). Batasan PRIMARY KEY menghasilkan indeks unik. Batasan FOREIGN KEY menghasilkan indeks non-unik. Batasan UNIQUE menghasilkan indeks unik jika semua kolom tidak dapat dinolkan, dan mereka menghasilkan indeks tidak unik jika satu atau lebih kolom dapat dinihilkan. Oleh karena itu, jika kolom atau kumpulan kolom memiliki batasan UNIQUE, PRIMARY KEY, atau FOREIGN KEY, Anda tidak perlu membuat indeks pada kolom tersebut untuk kinerja.

Chinmai
sumber
Dokumen yang Anda tautkan adalah untuk Derby, database Java tertanam, bukan untuk Oracle.
Davos