Berapa banyak indeks database yang terlalu banyak?

109

Saya sedang mengerjakan proyek dengan database Oracle yang agak besar (meskipun pertanyaan saya berlaku sama baiknya untuk database lain). Kami memiliki antarmuka web yang memungkinkan pengguna untuk mencari di hampir semua kemungkinan kombinasi bidang.

Untuk mempercepat pencarian ini, kami menambahkan indeks ke bidang dan kombinasi bidang yang kami yakini akan dicari oleh pengguna secara umum. Namun, karena kami tidak benar-benar tahu bagaimana pelanggan kami akan menggunakan perangkat lunak ini, sulit untuk membedakan indeks mana yang akan dibuat.

Ruang bukanlah masalah; kami memiliki drive RAID 4 terabyte yang hanya kami gunakan sebagian kecil. Namun, saya khawatir tentang kemungkinan penalti kinerja karena memiliki terlalu banyak indeks. Karena indeks tersebut perlu diperbarui setiap kali baris ditambahkan, dihapus, atau diubah, saya membayangkan akan menjadi ide yang buruk untuk memiliki lusinan indeks dalam satu tabel.

Jadi berapa indeks yang dianggap terlalu banyak? 10? 25? 50? Atau haruskah saya membahas kasus yang benar-benar umum dan jelas dan mengabaikan yang lainnya?

Eli Courtwright
sumber

Jawaban:

87

Itu tergantung pada operasi yang terjadi di atas meja.

Jika ada banyak SELECT dan sangat sedikit perubahan, indeks semua yang Anda suka .... ini (berpotensi) akan mempercepat pernyataan SELECT.

Jika tabel sangat terpukul oleh UPDATE, INSERTs + DELETEs ... ini akan sangat lambat dengan banyak indeks karena semuanya perlu dimodifikasi setiap kali salah satu operasi ini berlangsung

Karena itu, Anda dapat dengan jelas menambahkan banyak indeks yang tidak berguna ke tabel yang tidak akan melakukan apa pun. Menambahkan indeks B-Tree ke kolom dengan 2 nilai berbeda akan menjadi sia-sia karena tidak menambahkan apapun dalam hal mencari datanya. Semakin unik nilai dalam kolom, semakin besar manfaatnya dari indeks.

cagcowboy.dll
sumber
1
Hanya untuk memperjelas, indeks pada 2 nilai mungkin tidak ada gunanya dalam kasus tertentu, ketika satu nilai jarang terjadi dan Anda ingin mencarinya. Jadi ini bukan tentang seberapa unik nilainya, ini tentang seberapa selektif indeksnya.
charlie_pl
44

Saya biasanya melanjutkan seperti ini.

  1. Dapatkan log kueri nyata yang dijalankan pada data pada hari-hari biasa.
  2. Tambahkan indeks sehingga kueri yang paling penting mencapai indeks dalam rencana pelaksanaannya.
  3. Cobalah untuk menghindari pengindeksan bidang yang memiliki banyak pembaruan atau sisipan
  4. Setelah beberapa indeks, dapatkan log baru dan ulangi.

Seperti semua pengoptimalan lainnya, saya berhenti ketika kinerja yang diminta tercapai (ini jelas menyiratkan bahwa titik 0. akan mendapatkan persyaratan kinerja tertentu).

Sklivvz
sumber
26

Semua orang telah memberi Anda nasihat yang bagus. Saya memiliki saran tambahan untuk Anda saat Anda melangkah maju. Pada titik tertentu Anda harus membuat keputusan tentang strategi pengindeksan terbaik Anda. Namun pada akhirnya, strategi pengindeksan TERENCANA terbaik masih bisa membuat indeks yang akhirnya tidak digunakan. Salah satu strategi yang memungkinkan Anda menemukan indeks yang tidak digunakan adalah memantau penggunaan indeks. Anda melakukan ini sebagai berikut: -

alter index my_index_name monitoring usage;

Anda kemudian dapat memantau apakah indeks digunakan atau tidak sejak saat itu dengan menanyakan v $ object_usage. Informasi tentang ini dapat ditemukan di Panduan Administrator Database Oracle® .

Ingatlah bahwa jika Anda memiliki strategi pergudangan untuk menghapus indeks sebelum memperbarui tabel, lalu membuatnya kembali, Anda harus mengatur indeks untuk dipantau lagi, dan Anda akan kehilangan riwayat pemantauan untuk indeks tersebut.

Mike McAllister
sumber
14

Dalam pergudangan data, sangat umum untuk memiliki jumlah indeks yang tinggi. Saya telah bekerja dengan tabel fakta yang memiliki dua ratus kolom dan 190 di antaranya diindeks.

Meskipun ada biaya tambahan untuk ini, harus dipahami dalam konteks bahwa dalam gudang data kami biasanya hanya menyisipkan satu baris sekali, kami tidak pernah memperbaruinya, tetapi kemudian dapat berpartisipasi dalam ribuan kueri SELECT yang mungkin mendapat manfaat dari pengindeksan di salah satu kolom.

Untuk fleksibilitas maksimum, gudang data umumnya menggunakan indeks bitmap kolom tunggal kecuali pada kolom berkardinalitas tinggi, di mana indeks btree (terkompresi) dapat digunakan.

Overhead pada pemeliharaan indeks sebagian besar dikaitkan dengan biaya penulisan ke banyak blok dan blok terbelah karena baris baru ditambahkan dengan nilai yang berada "di tengah" rentang nilai yang ada untuk kolom itu. Ini dapat dikurangi dengan mempartisi dan memuat data baru yang selaras dengan skema partisi, dan dengan menggunakan sisipan jalur langsung.

Untuk menjawab pertanyaan Anda secara lebih langsung, saya pikir mungkin baik-baik saja untuk mengindeks yang sudah jelas pada awalnya, tetapi jangan takut untuk menambahkan lebih banyak indeks jika kueri terhadap tabel akan mendapat manfaat.

David Aldridge
sumber
Fakta sebanyak itu? Saya akan menebak Anda akan mengatakan dimensi. Itu kasus penggunaan yang agak aneh. Tapi, Anda keren sebagai DBA jadi saya akan mengatakan, saya jelas melewatkan sesuatu.
Stephanie Page
@ Stephanie, kami memiliki skenario yang hampir sama .. David telah menyebutkan bahwa itu adalah indeks bitmap. Kami juga menggunakan indeks BITMAP JOIN. Ya, berdasarkan fakta. Oracle dapat melakukan operasi AND yang sangat efisien pada indeks bitmap. Misalnya, Anda dapat memiliki klausa WHERE dengan 5 atribut berkardinalitas rendah yang masing-masing memiliki indeks bitmap. Jika Anda melihat rencana eksekusi, itu akan memiliki bitmap DAN operasi (pada dasarnya bitmap dan operasi yang efisien), kemudian di bawah rencana eksekusi Anda akan melihat konversi bitmap ke rowid. Ini sangat cepat.
Tagar
12

Dalam parafrase Einstein tentang kesederhanaan, tambahkan indeks sebanyak yang Anda butuhkan dan tidak lebih.

Serius, bagaimanapun, setiap indeks yang Anda tambahkan memerlukan pemeliharaan setiap kali data ditambahkan ke tabel. Pada tabel yang utamanya hanya baca, banyak indeks adalah hal yang baik. Pada tabel yang sangat dinamis, lebih sedikit lebih baik.

Saran saya adalah untuk membahas kasus yang umum dan jelas dan kemudian, saat Anda menghadapi masalah di mana Anda membutuhkan kecepatan lebih dalam mendapatkan data dari tabel tertentu, evaluasi dan tambahkan indeks pada saat itu.

Selain itu, sebaiknya evaluasi ulang skema pengindeksan Anda setiap beberapa bulan, hanya untuk melihat apakah ada sesuatu yang baru yang memerlukan pengindeksan atau indeks apa pun yang Anda buat yang tidak digunakan untuk apa pun dan harus disingkirkan. .

Josef
sumber
1
Saya setuju dengan evaluasi ulang. Administrasi yang baik tidak pernah menjadi tugas "atur dan lupakan". Perubahan perangkat lunak. Persyaratan berubah. Perubahan penggunaan. Fungsi baru yang tampaknya sepele yang diperkenalkan suatu hari dapat dengan cepat menjadi penghambat terbesar Anda, dan kode dasar roti-dan-mentega kemarin mungkin menjadi lemak yang tidak aktif dan tidak perlu yang hanya bergantung pada sumber daya yang dikonsumsi. Saya juga setuju dengan pendekatan berulang. Jika Anda melakukan terlalu banyak sekaligus, Anda tidak akan tahu apa yang berhasil.
durette
6

Selain poin yang telah dikumpulkan semua orang, Pengoptimal Berbasis Biaya menimbulkan biaya saat membuat rencana untuk pernyataan SQL jika ada lebih banyak indeks karena ada lebih banyak kombinasi untuk dipertimbangkan. Anda dapat mengurangi ini dengan benar menggunakan variabel bind sehingga pernyataan SQL tetap berada di cache SQL. Oracle kemudian dapat melakukan parsing lunak dan menggunakan kembali paket yang ditemukan terakhir kali.

Seperti biasa, tidak ada yang sederhana. Jika ada kolom dan histogram miring yang terlibat maka ini bisa menjadi ide yang buruk.

Dalam aplikasi web kami, kami cenderung membatasi kombinasi pencarian yang kami izinkan. Jika tidak, Anda harus menguji secara harfiah setiap kombinasi kinerja untuk memastikan Anda tidak memiliki masalah tersembunyi yang akan ditemukan seseorang suatu hari nanti. Kami juga telah menerapkan batas sumber daya untuk menghentikan ini menyebabkan masalah di tempat lain dalam aplikasi jika terjadi kesalahan.

WW.
sumber
Saya memilih tetapi ... Saya akan mengatakan waktu parse ekstra sementara menarik dan akademis, itu tidak akan pernah memengaruhi pilihan saya untuk jumlah indeks yang benar. setuju?
Stephanie Page
@StephaniePage Saya belum melakukan percobaan untuk membuktikan apa pun. Namun saya melihat proyek yang secara naif membuat indeks kolom tunggal di setiap kolom. Jika beberapa tabel memiliki 80 kolom, saya kira itu bisa mulai berdampak. Oracle tampaknya mempertimbangkan biaya akses oleh setiap indeks. Tapi ya, saya setuju, ada hal yang lebih penting untuk dipertimbangkan daripada ini.
WW.
Mmm ... Saya percaya bahwa ada jumlah maksimum waktu yang akan dihabiskan Oracle dalam penguraian keras ... pertimbangkan SQL dengan lebih dari beberapa tabel, katakanlah 7 atau 8, pilihan pesanan gabungan saja dapat menghasilkan ratusan kemungkinan jalur akses.
Stephanie Page
6

Saya membuat beberapa tes sederhana pada proyek saya yang sebenarnya dan database MySql yang sebenarnya. Saya sudah menjawab dalam topik ini: Berapa biaya untuk mengindeks beberapa kolom db?

Tapi saya rasa akan lebih baik jika saya mengutipnya di sini:

Saya membuat beberapa tes sederhana menggunakan proyek nyata saya dan database MySql asli.

Hasil saya adalah: menambahkan indeks rata-rata (1-3 kolom dalam indeks) ke tabel - membuat penyisipan lebih lambat sebesar 2,1%. Jadi, jika Anda menambahkan 20 indeks, penyisipan Anda akan lebih lambat 40-50%. Tapi pilihan Anda akan 10-100 kali lebih cepat.

Jadi, apakah boleh menambahkan banyak indeks? - Itu tergantung :) Saya memberikan hasil saya - Anda yang memutuskan!

nightcoder
sumber
Ini tidak boleh dianggap sebagai ramalan tanpa semua detailnya. Terutama karena Anda tidak dapat melipatgandakan keuntungan / kerugian kinerja dari satu tindakan ke tindakan lainnya. Basisnya tetap sama: tambahkan lebih banyak indeks dan sisipan Anda pada akhirnya akan lebih lambat karena rekreasi indeks.
SovietFrontier
3

Pada akhirnya, berapa banyak indeks yang Anda perlukan bergantung pada perilaku aplikasi Anda yang berada di atas server database Anda.

Secara umum, semakin banyak memasukkan Anda, semakin menyakitkan indeks Anda jadinya. Setiap kali Anda melakukan penyisipan, semua indeks yang menyertakan tabel itu harus diperbarui.

Sekarang jika aplikasi Anda memiliki jumlah bacaan yang layak, atau bahkan lebih jika hampir semua membaca, maka indeks adalah cara yang tepat karena akan ada peningkatan kinerja yang besar dengan biaya yang sangat sedikit.

Orion Adrian
sumber
3

Tidak ada jawaban statis menurut saya, hal semacam ini termasuk dalam 'penyetelan kinerja'.

Bisa jadi semua yang dilakukan aplikasi Anda dicari oleh kunci utama, atau bisa juga sebaliknya dalam kueri yang dilakukan melalui kombinasi bidang yang tidak dibatasi dan salah satu secara khusus dapat digunakan pada waktu tertentu.

Selain pengindeksan, ada reogranizing DB Anda untuk menyertakan bidang pencarian yang dihitung, memisahkan tabel, dll - itu benar-benar tergantung pada bentuk beban Anda dan parameter kueri, berapa banyak / data apa yang 'sebenarnya' perlu ditarik oleh kueri.

Jika seluruh DB Anda digawangi oleh proses penyimpanan fasad yang berubah menjadi sedikit lebih mudah, karena Anda tidak perlu mengkhawatirkan setiap kueri ad-hoc. Atau Anda mungkin memiliki pemahaman yang mendalam tentang jenis kueri yang akan mencapai DB Anda, dan dapat membatasi penyetelan untuk itu.

Untuk SQL Server, saya menemukan penasihat Database Engine Tuning berguna - Anda mengatur beban kerja 'khas' dan dapat membuat rekomendasi tentang menambahkan / menghapus indeks dan statistik. Saya yakin DB lain memiliki alat serupa, baik 'resmi' atau pihak ketiga.

scotta
sumber
3

Ini benar-benar pertanyaan yang lebih teoritis daripada praktis. Indeks berdampak pada kinerja Anda tergantung pada perangkat keras yang Anda miliki, versi Oracle, jenis indeks, dll. Kemarin saya mendengar Oracle mengumumkan penyimpanan khusus, dibuat oleh HP, yang seharusnya bekerja 10 kali lebih cepat dengan database 11g. Untuk kasus Anda, ada beberapa solusi: 1. Buat indeks dalam jumlah besar (> 20) dan buat ulang setiap hari (setiap malam). Ini akan sangat berguna jika tabel mendapat ribuan pembaruan / penghapusan setiap hari. 2. Partisi tabel Anda (jika itu menerapkan model data Anda). 3. Gunakan tabel terpisah untuk data baru / yang diperbarui, dan jalankan proses setiap malam yang menggabungkan data tersebut. Ini akan membutuhkan perubahan dalam logika aplikasi Anda. 4. Beralih ke IOT (tabel terorganisir indeks), jika data Anda mendukung ini.

Tentu mungkin ada lebih banyak solusi untuk kasus seperti itu. Saran pertama saya untuk Anda, adalah mengkloning DB ke lingkungan pengembangan, dan menjalankan beberapa pengujian stres terhadapnya.

Moshe
sumber
Saya tidak mengerti bagaimana membangun kembali indeks akan membantu, atau bagaimana IOT akan membantu.
David Aldridge
IOT - jika memungkinkan untuk mendesain ulang aplikasi, sehingga tipe data yang ditentukan pengguna baru digunakan, maka IOT akan menghemat biaya overhead untuk mengindeks tabel. ini mungkin tidak terjadi di sini. itu sangat tergantung. membangun kembali indeks - jika ada banyak indeks, dan data baru tidak diindeks.
Moshe
IOT masih merupakan struktur indeks, dengan lebih banyak overhead pada pemecahan blok daripada indeks biasa. "membangun kembali indeks - jika ada banyak indeks, dan data baru tidak diindeks" ... RDBMS mana yang Anda bicarakan yang tidak memelihara indeks secara otomatis untuk entri baru?
David Aldridge
David - Anda benar tentu saja. Saya mencampurnya dengan kemampuan SQL Server untuk mengindeks Pencarian Teks Lengkap hanya berdasarkan permintaan. Berharap Oracle memilikinya, karena itu bisa berguna dalam kasus ini. Saya akan merekomendasikan untuk tetap menggunakan dua saran lainnya.
Moshe
2

Jika Anda kebanyakan membaca (dan sedikit pembaruan) maka tidak ada alasan untuk tidak mengindeks semua yang Anda perlukan untuk mengindeks. Jika Anda sering memperbarui, Anda mungkin perlu berhati-hati tentang berapa banyak indeks yang Anda miliki. Tidak ada angka pasti, tetapi Anda akan melihat ketika segala sesuatunya mulai melambat. Pastikan indeks berkerumun Anda adalah yang paling masuk akal berdasarkan data.

Bob King
sumber
2

Satu hal yang dapat Anda pertimbangkan adalah membuat indeks untuk menargetkan kombinasi pencarian standar. Jika kolom1 biasanya dicari, dan kolom2 sering digunakan dengannya, dan kolom3 kadang-kadang digunakan dengan kolom2 dan kolom1, maka indeks pada kolom1, kolom2, dan kolom3 dalam urutan itu dapat digunakan untuk salah satu dari ketiga keadaan tersebut, meskipun demikian hanya satu indeks yang harus dipertahankan.

Jeffrey L. Whitledge
sumber
2

Indeks membebankan biaya saat tabel yang mendasari diperbarui. Indeks memberikan manfaat saat digunakan untuk mempercepat kueri. Untuk setiap indeks, Anda perlu menyeimbangkan biaya dengan keuntungannya. Seberapa lambat kueri berjalan tanpa indeks? Seberapa besar keuntungan berlari lebih cepat? Dapatkah Anda atau pengguna Anda mentolerir kecepatan lambat saat indeks hilang?

Dapatkah Anda mentolerir waktu tambahan yang diperlukan untuk menyelesaikan pembaruan?

Anda perlu membandingkan biaya dan manfaat. Itu khusus untuk situasi Anda. Tidak ada angka ajaib indeks yang melewati ambang batas "terlalu banyak".

Ada juga biaya ruang yang diperlukan untuk menyimpan indeks, tetapi Anda telah mengatakan bahwa dalam situasi Anda itu bukan masalah. Hal yang sama juga berlaku dalam kebanyakan situasi, mengingat betapa murahnya ruang disk.

Walter Mitty
sumber
1

Ada berapa kolom? Saya selalu diberitahu untuk membuat indeks satu kolom, bukan indeks multi-kolom. Jadi indeks tidak lebih dari jumlah kolom, IMHO.

lamcro.dll
sumber
1

Apa yang sebenarnya terjadi adalah, jangan menambahkan indeks kecuali Anda tahu (dan ini sering berarti mengumpulkan statistik penggunaan) bahwa itu akan digunakan jauh lebih sering daripada diperbarui.

Setiap indeks yang tidak memenuhi kriteria itu akan membebani Anda lebih banyak untuk membangun kembali daripada hukuman kinerja karena tidak memilikinya dalam kasus aneh itu digunakan.

Torbjörn Gyllebring
sumber
1

Server Sql memberi Anda beberapa alat bagus yang memungkinkan Anda melihat indeks mana yang sebenarnya sedang digunakan. Artikel ini, http://www.mssqltips.com/tip.asp?tip=1239 , memberi Anda beberapa pertanyaan yang memungkinkan Anda mendapatkan pemahaman yang lebih baik tentang seberapa banyak indeks digunakan, bukan seberapa banyak indeks tersebut diperbarui.

aboy021
sumber
0

Ini sepenuhnya didasarkan pada kolom yang digunakan dalam Klausa Dimana. Dan sebagai Thumb of Rule, kita harus memiliki indeks pada Kolom Kunci Asing untuk menghindari DEADLOCKS. Laporan AWR harus menganalisis secara berkala untuk memahami kebutuhan indeks.

P Sharma
sumber
2
Indeks pada kolom kunci asing untuk menghindari kebuntuan? Apakah Anda memiliki referensi yang menjelaskan mengapa dan bagaimana ini terjadi?
Jay Sullivan