Saya sudah membaca tentang composite indexes
dan saya sedikit bingung tentang memesan. Dokumentasi ini (sedikit kurang dari setengah jalan) mengatakan
Secara umum, Anda harus meletakkan kolom yang diharapkan paling sering digunakan pertama kali dalam indeks.
Namun, tak lama setelah itu dikatakan
buat indeks komposit dengan menempatkan kolom paling selektif terlebih dahulu; yaitu kolom dengan nilai terbanyak.
Oracle juga mengatakannya di sini dengan kata lain
Jika semua kunci digunakan dalam klausa WHERE sama seringnya, maka memesan kunci ini dari yang paling selektif ke yang paling selektif dalam pernyataan CREATE INDEX terbaik meningkatkan kinerja permintaan.
Namun, saya telah menemukan jawaban SO yang mengatakan berbeda. Ia mengatakan
Atur kolom dengan kolom paling selektif terlebih dahulu dan kolom paling selektif terakhir. Dalam kasus dasi timbal dengan kolom yang lebih mungkin digunakan sendiri.
Dokumentasi pertama yang saya referensikan mengatakan bahwa Anda harus pergi dulu dengan yang paling sering digunakan sedangkan jawaban SO mengatakan bahwa seharusnya hanya untuk melanggar dasi. Kemudian mereka juga berbeda dalam pemesanan.
Dokumentasi ini juga berbicara tentang skip scanning
dan mengatakan
Melewati pemindaian menguntungkan jika ada beberapa nilai berbeda di kolom terkemuka indeks komposit dan banyak nilai berbeda dalam kunci nonleading indeks.
Artikel lain mengatakan
Kolom awalan harus menjadi yang paling diskriminatif dan paling banyak digunakan dalam kueri
yang saya percaya paling diskriminatif berarti paling khas.
Semua penelitian ini masih mengarahkan saya ke pertanyaan yang sama; haruskah kolom paling selektif menjadi yang pertama atau terakhir? Haruskah kolom pertama menjadi yang paling banyak digunakan dan hanya yang paling selektif pada tie-break?
Artikel-artikel ini tampaknya saling bertentangan, tetapi mereka menawarkan beberapa contoh. Dari apa yang telah saya kumpulkan, tampaknya lebih efisien untuk least selective column
menjadi yang pertama dalam memesan jika Anda mengantisipasi Index Skip Scans
. Tetapi saya tidak begitu yakin apakah itu benar.
sumber
Jawaban:
Dari AskTom
Salah satu argumen untuk mengatur kolom dalam indeks komposit dalam urutan dari yang paling tidak diskriminatif (nilai yang berbeda) ke yang paling diskriminatif (nilai yang lebih berbeda) adalah untuk kompresi kunci indeks.
Menurut statistik indeks, indeks pertama lebih kompresif.
Lain adalah bagaimana indeks digunakan dalam permintaan Anda. Jika sebagian besar pertanyaan Anda menggunakan
col1
,Misalnya, jika Anda memiliki pertanyaan seperti-
select * from t where col1 = :a and col2 = :b;
select * from t where col1 = :a;
-Kemudian
index(col1,col2)
akan tampil lebih baik.Jika sebagian besar pertanyaan Anda menggunakan
col2
,select * from t where col1 = :a and col2 = :b;
select * from t where col2 = :b;
-Kemudian
index(col2,col1)
akan tampil lebih baik. Jika semua pertanyaan Anda selalu menentukan kedua kolom, maka tidak masalah kolom mana yang lebih dulu berada di indeks komposit.Sebagai kesimpulan, pertimbangan utama dalam pemesanan kolom indeks komposit adalah kompresi kunci indeks dan bagaimana Anda akan menggunakan indeks ini dalam permintaan Anda.
Referensi:
sumber
Paling selektif pertama hanya berguna ketika kolom ini berada di klausa WHERE yang sebenarnya.
Ketika SELECT adalah dengan kelompok yang lebih besar (kurang selektif), dan kemudian mungkin dengan nilai lain yang tidak diindeks, indeks dengan kolom yang kurang selektif mungkin masih berguna (jika ada alasan untuk tidak membuat yang lain).
Jika ada ALAMAT tabel, dengan
JALAN KOTA NEGARA, sesuatu yang lain ...
pengindeksan STREET, CITY, COUNTRY akan menghasilkan kueri tercepat dengan nama jalan. Tetapi menanyakan semua jalan kota, indeks tidak akan berguna, dan kueri kemungkinan akan melakukan pemindaian tabel penuh.
Pengindeksan NEGARA, KOTA, JALAN mungkin sedikit lebih lambat untuk setiap jalan, tetapi indeks dapat digunakan untuk kueri lain, hanya memilih menurut negara dan / atau kota.
sumber
Saat memilih urutan kolom indeks, perhatian utama adalah:
Apakah ada (kesetaraan) predikat terhadap kolom ini di kueri saya?
Jika sebuah kolom tidak pernah muncul dalam klausa where, itu tidak layak diindeks (1)
OK, jadi Anda punya tabel dan kueri terhadap setiap kolom. Terkadang lebih dari satu.
Bagaimana Anda memutuskan apa yang akan diindeks?
Mari kita lihat sebuah contoh. Berikut adalah tabel dengan tiga kolom. Satu memiliki 10 nilai, 1.000 lainnya, 10.000 terakhir:
Ini adalah angka yang dibiarkan penuh dengan nol. Ini akan membantu menjelaskan tentang kompresi nanti.
Jadi, Anda memiliki tiga pertanyaan umum:
Apa yang Anda indeks?
Indeks hanya pada few_vals hanya sedikit lebih baik daripada pemindaian tabel lengkap:
Jadi tidak mungkin untuk mengindeks sendiri. Kueri pada lots_vals mengembalikan beberapa baris (hanya 1 dalam kasus ini). Jadi ini pasti layak diindeks.
Tetapi bagaimana dengan pertanyaan terhadap kedua kolom?
Haruskah Anda mengindeks:
ATAU
Pertanyaan jebakan!
Jawabannya adalah tidak.
Tentu, few_vals adalah string yang panjang. Jadi Anda bisa mendapatkan kompresi yang baik dari itu. Dan Anda (mungkin) mendapatkan pemindaian lompatan indeks untuk kueri menggunakan (few_vals, lots_vals) yang hanya memiliki predikat pada lots_vals. Tapi saya tidak di sini, meskipun kinerjanya jauh lebih baik daripada pemindaian penuh:
Apakah Anda suka judi? (2)
Jadi, Anda masih memerlukan indeks dengan lots_vals sebagai kolom utama. Dan setidaknya dalam hal ini indeks gabungan (beberapa, lot) melakukan jumlah pekerjaan yang sama dengan satu pada hanya (banyak)
Akan ada kasus di mana indeks gabungan menghemat 1-2 IOs. Tetapi apakah layak memiliki dua indeks untuk penghematan ini?
Dan ada masalah lain dengan indeks komposit. Bandingkan faktor pengelompokan untuk tiga indeks termasuk LOTS_VALS:
Perhatikan bahwa faktor pengelompokan untuk few_lots adalah 10x lebih tinggi daripada untuk banyak dan banyak_few! Dan ini ada di tabel demo dengan pengelompokan yang sempurna untuk memulai. Dalam database dunia nyata pengaruhnya mungkin lebih buruk.
Jadi apa yang buruk tentang itu?
Faktor pengelompokan adalah salah satu pendorong utama yang menentukan seberapa "menarik" suatu indeks. Semakin tinggi, semakin kecil kemungkinan pengoptimal untuk memilihnya. Terutama jika lots_vals sebenarnya tidak unik, tetapi biasanya masih memiliki beberapa baris per nilai. Jika Anda kurang beruntung ini bisa cukup untuk membuat pengoptimal berpikir pemindaian lengkap lebih murah ...
OK, jadi indeks gabungan dengan few_vals dan lots_vals hanya memiliki manfaat tepi kasus.
Bagaimana dengan kueri yang memfilter few_vals dan many_vals?
Indeks kolom tunggal hanya memberikan manfaat kecil. Tetapi gabungan mereka mengembalikan beberapa nilai. Jadi indeks komposit adalah ide yang bagus. Tapi ke arah mana?
Jika Anda menempatkan sedikit lebih dulu, mengompresi kolom terkemuka akan membuatnya lebih kecil
Dengan nilai yang berbeda lebih sedikit di kolom terkemuka kompres lebih baik. Jadi ada sedikit pekerjaan untuk membaca indeks ini. Namun hanya sedikit. Dan keduanya sudah merupakan bagian yang baik lebih kecil dari yang asli (ukuran 25% berkurang).
Dan Anda dapat melangkah lebih jauh dan kompres seluruh indeks!
Sekarang kedua indeks kembali ke ukuran yang sama. Perhatikan ini mengambil keuntungan dari fakta ada hubungan antara sedikit dan banyak. Sekali lagi tidak mungkin Anda akan melihat manfaat semacam ini di dunia nyata.
Sejauh ini kami hanya berbicara tentang pemeriksaan kesetaraan. Seringkali dengan indeks komposit Anda akan memiliki ketimpangan terhadap salah satu kolom. mis. pertanyaan seperti "dapatkan pesanan / pengiriman / faktur untuk pelanggan dalam N hari terakhir".
Jika Anda memiliki pertanyaan seperti ini, Anda ingin persamaan terhadap kolom pertama dari indeks:
Perhatikan mereka menggunakan indeks yang berlawanan.
TL; DR
1: Dalam beberapa kasus mungkin ada baiknya menyertakan kolom dalam indeks jika ini berarti semua kolom dalam kueri Anda ada dalam indeks. Ini memungkinkan hanya pemindaian indeks, sehingga Anda tidak perlu mengakses tabel.
2: Jika Anda memiliki lisensi untuk Diagnostik dan Tuning, Anda bisa memaksa rencana untuk melewati pemindaian dengan SQL Plan Management
ADDEDNDA
PS - dokumen yang Anda kutip dari 9i. Itu benar-benar tua. Saya akan tetap dengan sesuatu yang lebih baru
sumber
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
benar - benar umum? Tidakkah Oracle mengizinkan sintaksisselect count (distinct few_vals, many_vals, lots_vals )
- yang tidak melakukan penggabungan string, tidak memerlukan kolom untuk menjadi tipe teks dan tidak bergantung pada ketiadaan:
karakter?count ( distinct x, y, z )
di Oracle. Jadi, Anda perlu melakukan subquery yang berbeda dan menghitung hasil atau gabungan seperti di atas. Saya hanya melakukannya di sini untuk memaksa akses tabel (daripada hanya memindai indeks) dan hanya memiliki satu baris dalam hasilnyaAda lebih banyak elemen kueri yang berkontribusi pada keputusan akhir tentang apa yang harus dimulai dengan Indeks Komposit dan / atau mengandung selain selektivitas kolom.
sebagai contoh:
">,> =, <, <="
namun untuk menjaga agar percakapan tetap relevan, jawaban saya di bawah ini berlaku untuk situasi berikut:
string"
Dalam pengalaman saya, itu adalah DBA yang harus diperhatikan.
1) Jika saya membuat indeks dengan kolom paling selektif menjadi yang pertama tetapi kolom itu tidak benar-benar digunakan oleh sebagian besar pertanyaan pada tabel itu daripada tidak digunakan untuk mesin db.
2) Jika saya membuat indeks dengan kolom yang paling banyak digunakan dalam kueri menjadi yang pertama dalam indeks tetapi kolom memiliki selektivitas yang rendah daripada juga kinerja permintaan saya tidak akan baik.
Saya akan mencantumkan kolom yang sebagian besar digunakan dalam 90% kueri tabel. Kemudian, letakkan semua itu hanya dalam urutan kardinalitas paling rendah hingga kardinalitas terendah.
Kami menggunakan indeks untuk meningkatkan kinerja kueri baca dan alur kerja itu (jenis kueri baca) hanya akan mendorong pembuatan indeks. Bahkan ketika data tumbuh (miliaran baris) indeks terkompresi dapat menghemat penyimpanan tetapi tentu saja merusak kinerja permintaan baca.
sumber
Secara teori, kolom paling selektif menghasilkan pencarian tercepat. Tetapi di tempat kerja saya hanya tersandung pada situasi di mana kita memiliki indeks komposit 3 bagian dengan bagian paling selektif terlebih dahulu. (tanggal, penulis, perusahaan penerbitan katakanlah, dalam urutan itu, monitor meja diacungi jempol pada posting) dan saya memiliki permintaan yang menggunakan semua 3 bagian. Mysql default untuk menggunakan indeks penulis hanya melewatkan indeks komposit yang mengandung perusahaan dan tanggal meskipun mereka hadir dalam permintaan saya. Saya menggunakan indeks paksa untuk menggunakan komposit dan permintaan benar-benar berjalan lebih lambat. Mengapa itu terjadi? Saya akan memberi tahu Anda:
Saya memilih rentang pada tanggal tersebut, jadi meskipun tanggal tersebut sangat selektif, fakta bahwa kami menggunakannya untuk pemindaian rentang (meskipun rentangnya relatif pendek, 6 bulan dari 6 tahun data) membuat komposit berbahaya untuk mysql. Untuk menggunakan komposit dalam kasus tertentu, mysql harus mengambil semua artikel yang ditulis sejak tahun-tahun baru kemudian masuk ke dalam siapa penulisnya, dan mengingat bahwa penulis belum menulis banyak artikel dibandingkan dengan penulis lain, mysql lebih suka untuk hanya menemukan penulis itu .
Dalam kasus lain, kueri berjalan jauh lebih cepat pada komposit, kasusnya adalah ketika seorang penulis sangat populer dan memiliki sebagian besar catatan, mengurutkan berdasarkan tanggal masuk akal. Tetapi mysql tidak secara otomatis mendeteksi kasing itu, saya harus memaksa indeks ... Jadi, Anda tahu, ini bervariasi. Pemindaian rentang dapat membuat kolom selektif Anda tidak berguna. Distribusi data dapat membuat kasus di mana kolom lebih selektif untuk catatan yang berbeda ...
Apa yang akan saya lakukan secara berbeda adalah menggeser tanggal (yang lagi-lagi, dalam teori adalah yang paling selektif) ke kanan, karena saya tahu saya akan melakukan pemindaian jarak di atasnya sekarang dan itu membuat perbedaan.
sumber
WHERE (date BETWEEN @x AND @y) AND (author = @a) AND (publishing company = @p)
maka indeks pada(author, publishing_company, date)
atau pada(publishing_company, author, date)
akan lebih baik dan akan digunakan - tanpa memaksanya.Kasus berbeda untuk situasi berbeda. Kenali tujuan Anda; kemudian buat indeks Anda dan jalankan menjelaskan rencana untuk masing-masing dan Anda akan memiliki jawaban terbaik untuk situasi Anda.
sumber
Dari Urutan kolom dalam Indeks pada Tanya Tom:
Setuju, bahwa kita harus memesan kolom berdasarkan klausa where, tetapi pernyataan "(selektivitas a atau b tidak dihitung sama sekali)" tidak benar.) ". Kolom yang paling selektif harus memimpin jika memenuhi peran pertama ("di mana klausa")
sumber