Kolom apa yang umumnya membuat indeks bagus?

98

Sebagai tindak lanjut dari " Apa itu indeks dan bagaimana cara menggunakannya untuk mengoptimalkan kueri dalam database saya? " Di mana saya mencoba mempelajari tentang indeks, kolom apa yang merupakan kandidat indeks yang baik? Khusus untuk database MS SQL?

Setelah beberapa googling, semua yang saya baca menunjukkan bahwa kolom yang umumnya meningkat dan unik membuat indeks yang baik (hal-hal seperti auto_increment MySQL), saya mengerti ini, tetapi saya menggunakan MS SQL dan saya menggunakan GUID untuk kunci utama, jadi sepertinya bahwa indeks tidak akan menguntungkan kolom GUID ...

mmattax
sumber
Bagaimana dengan "buku masak": mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Jawaban:

110

Indeks dapat memainkan peran penting dalam pengoptimalan kueri dan mencari hasil dengan cepat dari tabel. Jadi, ini adalah langkah paling penting untuk memilih kolom mana yang akan diindeks. Ada dua tempat utama di mana kita dapat mempertimbangkan pengindeksan: kolom yang direferensikan di klausa WHERE dan kolom yang digunakan dalam klausa JOIN. Singkatnya, kolom seperti itu harus diindeks sehingga Anda diminta untuk mencari catatan tertentu. Misalkan, kami memiliki tabel bernama pembeli di mana kueri SELECT menggunakan indeks seperti di bawah ini:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Karena "buyer_id" direferensikan di bagian SELECT, MySQL tidak akan menggunakannya untuk membatasi baris yang dipilih. Karenanya, tidak ada kebutuhan besar untuk mengindeksnya. Di bawah ini adalah contoh lain yang sedikit berbeda dari yang di atas:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Menurut kueri first_name di atas, kolom last_name dapat diindeks karena berada di klausa WHERE. Juga bidang tambahan, country_id from country table, dapat dipertimbangkan untuk pengindeksan karena berada dalam klausa JOIN. Jadi pengindeksan dapat dipertimbangkan di setiap bidang di klausa WHERE atau klausa JOIN.

Daftar berikut ini juga menawarkan beberapa tip yang harus selalu Anda ingat saat bermaksud membuat indeks ke dalam tabel Anda:

  • Hanya indeks kolom yang diperlukan dalam klausa WHERE dan ORDER BY. Kolom pengindeksan yang melimpah akan menghasilkan beberapa kerugian.
  • Cobalah untuk memanfaatkan fitur "indeks awalan" atau "indeks multi-kolom" dari MySQL. Jika Anda membuat indeks seperti INDEX (first_name, last_name), jangan buat INDEX (first_name). Namun, "indeks awalan" atau "indeks multi-kolom" tidak disarankan dalam semua kasus pencarian.
  • Gunakan atribut NOT NULL untuk kolom-kolom yang Anda pertimbangkan untuk diindeks, sehingga nilai NULL tidak akan pernah disimpan.
  • Gunakan opsi --log-long-format untuk mencatat kueri yang tidak menggunakan indeks. Dengan cara ini, Anda dapat memeriksa file log ini dan menyesuaikan kueri Anda.
  • Pernyataan EXPLAIN membantu Anda mengungkapkan bahwa MySQL akan menjalankan kueri. Ini menunjukkan bagaimana dan dalam tabel urutan apa digabungkan. Ini bisa sangat berguna untuk menentukan cara menulis kueri yang dioptimalkan, dan apakah kolom perlu diindeks.

Pembaruan (23 Feb'15):

Indeks apa pun (baik / buruk) meningkatkan waktu penyisipan dan pembaruan.

Bergantung pada indeks Anda (jumlah indeks dan jenis), hasil dicari. Jika waktu pencarian Anda akan meningkat karena indeks maka itu indeks yang buruk.

Kemungkinan besar di buku manapun, "Halaman Indeks" bisa memiliki halaman awal bab, nomor halaman topik dimulai, juga halaman sub topik dimulai. Beberapa klarifikasi di halaman Indeks membantu tetapi indeks yang lebih rinci mungkin membingungkan Anda atau membuat Anda takut. Indeks juga memiliki memori.

Pemilihan indeks harus bijaksana. Ingatlah bahwa tidak semua kolom membutuhkan indeks.

Somnath Muluk
sumber
Terima kasih Somnath, Jadi, apakah ini berarti indeks hanya boleh dibuat untuk kolom yang akan kami gunakan WHERE, JOINSatau HAVING?
Muhammad Babar
3
Ya, gunakan indeks untuk kolom di mana Anda berencana menggunakan WHERE, JOINS atau HAVING. Namun perlu diingat, semua kolom kondisi tidak memerlukan indeks. Kadang-kadang di mana kolom kondisi hanya digunakan sekali sehingga mungkin tidak memerlukan indeks sedangkan kolom kondisi lain digunakan di banyak query jadi lebih memilih untuk mengindeks kolom tersebut.
Somnath Muluk
1
Jawaban akan mendapatkan keuntungan dari menempatkan, "kolom yang direferensikan di klausa WHERE dan kolom yang digunakan dalam klausa JOIN" di bagian TL; DR.
jpmc26
Jadi Anda mengatakan bahwa jika dalam WHEREklausa saya, saya memeriksa nilai bidang di mana kolomnya hanya dapat mengambil dua nilai, maka saya harus mengindeks kolom biner itu? Sepertinya ini salah.
AjaxLeung
@AjaxLeung: Ingat pepatah Knuth "Optimasi Dini adalah akar dari semua Kejahatan.". Anda dapat membuat indeks pada kolom biner, tetapi itu harus bergantung pada berapa biayanya (seperti penyisipan, waktu pembaruan). Jika logika bisnis Anda sering bergantung pada sakelar biner itu, maka kolom biner mungkin diperlukan untuk memiliki indeks.
Somnath Muluk
20

Beberapa orang menjawab pertanyaan serupa di sini: Bagaimana Anda tahu apa itu indeks yang baik?

Pada dasarnya, ini sangat tergantung pada bagaimana Anda akan menanyakan data Anda. Anda menginginkan indeks yang dengan cepat mengidentifikasi subset kecil dari kumpulan data Anda yang relevan dengan kueri. Jika Anda tidak pernah membuat kueri berdasarkan stempel tanggal, Anda tidak memerlukan indeks di atasnya, meskipun sebagian besar unik. Jika yang Anda lakukan hanyalah mendapatkan peristiwa yang terjadi dalam rentang tanggal tertentu, Anda pasti menginginkannya. Dalam kebanyakan kasus, indeks tentang jenis kelamin tidak ada gunanya - tetapi jika yang Anda lakukan hanyalah mendapatkan statistik tentang semua pria, dan secara terpisah, tentang semua wanita, mungkin ada baiknya Anda membuatnya. Cari tahu bagaimana pola kueri Anda nantinya, dan akses ke parameter mana yang paling mempersempit ruang pencarian, dan itulah indeks terbaik Anda.

Juga pertimbangkan jenis indeks yang Anda buat - Pohon-B baik untuk banyak hal dan memungkinkan kueri rentang, tetapi indeks hash membawa Anda langsung ke intinya (tetapi tidak mengizinkan rentang). Jenis indeks lain memiliki pro dan kontra lainnya.

Semoga berhasil!

SquareCog
sumber
9

Itu semua tergantung pada pertanyaan apa yang ingin Anda tanyakan tentang tabel. Jika Anda meminta semua baris dengan nilai tertentu untuk kolom X, Anda harus melakukan pemindaian tabel lengkap jika indeks tidak dapat digunakan.

Indeks akan berguna jika:

  • Kolom atau kolom memiliki tingkat keunikan yang tinggi
  • Anda sering kali perlu mencari nilai atau rentang nilai tertentu untuk kolom tersebut.

Mereka tidak akan berguna jika:

  • Anda memilih% besar (> 10-20%) baris di tabel
  • Penggunaan ruang tambahan menjadi masalah
  • Anda ingin memaksimalkan kinerja penyisipan. Setiap indeks pada tabel mengurangi kinerja penyisipan dan pembaruan karena harus diperbarui setiap kali data berubah.

Kolom kunci utama biasanya bagus untuk pengindeksan karena unik dan sering digunakan untuk mencari baris.

Plasmer
sumber
pencarian string di mana nilainya bisa berada di mana saja di dalam string mungkin membuatnya tidak menggunakan indeks tersebut dalam kasus itu.
Arthur Thomas
5

Secara umum (saya tidak menggunakan mssql jadi tidak bisa berkomentar secara khusus), kunci utama membuat indeks yang baik. Mereka unik dan harus memiliki nilai yang ditentukan. (Selain itu, kunci utama membuat indeks yang baik sehingga biasanya dibuat indeks secara otomatis.)

Indeks secara efektif adalah salinan kolom yang telah diurutkan untuk memungkinkan pencarian biner (yang jauh lebih cepat daripada pencarian linier). Sistem database dapat menggunakan berbagai trik untuk lebih mempercepat pencarian, terutama jika datanya lebih kompleks daripada angka sederhana.

Saran saya adalah untuk tidak menggunakan indeks apa pun pada awalnya dan membuat profil kueri Anda. Jika kueri tertentu (seperti menelusuri orang berdasarkan nama belakang, misalnya) sangat sering dijalankan, coba buat indeks di atas atribut dan profil yang relevan lagi. Jika ada percepatan yang nyata pada kueri dan perlambatan yang dapat diabaikan pada penyisipan dan pembaruan, pertahankan indeks.

(Maaf jika saya mengulangi hal-hal yang disebutkan dalam pertanyaan Anda yang lain, saya belum pernah menemukannya sebelumnya.)

Zooba
sumber
5

Setiap kolom yang akan secara teratur digunakan untuk mengekstrak data dari tabel harus diindeks.

Ini termasuk: kunci asing -

select * from tblOrder where status_id=:v_outstanding

bidang deskriptif -

select * from tblCust where Surname like "O'Brian%"

Kolom tidak harus unik. Nyatanya, Anda bisa mendapatkan kinerja yang sangat bagus dari indeks biner saat mencari pengecualian.

select * from tblOrder where paidYN='N'
pappes
sumber
Penyebutan eksplisit Anda tentang kunci asing benar-benar menjelaskan segalanya bagi saya mempertimbangkan untuk bergabung.
pfabri
3

Ini sangat tergantung pada pertanyaan Anda. Misalnya, jika Anda hampir hanya menulis ke tabel maka yang terbaik adalah tidak memiliki indeks apa pun, mereka hanya memperlambat penulisan dan tidak pernah digunakan. Setiap kolom yang Anda gunakan untuk bergabung dengan tabel lain adalah kandidat yang baik untuk indeks.

Juga, baca tentang fitur Indeks yang Hilang. Ini memonitor kueri aktual yang digunakan terhadap database Anda dan dapat memberi tahu Anda indeks apa yang akan meningkatkan kinerja.

jwanagel.dll
sumber
3

Kolom GUID bukanlah kandidat terbaik untuk pengindeksan. Indeks paling cocok untuk kolom dengan tipe data yang dapat diberi urutan yang bermakna, misalnya diurutkan (bilangan bulat, tanggal dll).

Tidak masalah jika data dalam kolom umumnya bertambah. Jika Anda membuat indeks pada kolom, indeks akan membuat struktur datanya sendiri yang hanya akan mereferensikan item aktual dalam tabel Anda tanpa memperhatikan pesanan tersimpan (indeks non-cluster). Kemudian misalnya, pencarian biner dapat dilakukan pada struktur data indeks Anda untuk menyediakan pengambilan yang cepat.

Anda juga dapat membuat "indeks berkerumun" yang akan menyusun ulang data Anda secara fisik. Namun Anda hanya dapat memiliki salah satu dari ini per tabel, sedangkan Anda dapat memiliki beberapa indeks non-cluster.

Abu
sumber
Nah, itu tidak sepenuhnya akurat. Anda dapat dengan mudah membuat indeks biasa dan non-cluster pada kolom GUID - mengapa tidak? GUID memiliki kelemahan besar jika Anda menggunakannya sebagai kunci pengelompokan (misalnya untuk CLUSTERED INDEX) - maka sebaiknya gunakan.
marc_s
1

Aturan praktisnya adalah kolom yang banyak digunakan dalam klausa WHERE, ORDER BY, dan GROUP BY, atau kolom apa pun yang tampaknya sering digunakan dalam join. Ingatlah bahwa saya mengacu pada indeks, BUKAN Kunci Utama

Bukan untuk memberikan jawaban 'vanilla-ish', tetapi itu benar-benar tergantung pada bagaimana Anda mengakses data

curug
sumber
1

Kunci utama Anda harus selalu berupa indeks. (Sebenarnya saya akan terkejut jika tidak secara otomatis diindeks oleh MS SQL.) Anda juga harus mengindeks kolom Anda SELECTatauORDER sering; tujuan mereka adalah pencarian cepat dari satu nilai dan pengurutan yang lebih cepat.

Satu-satunya bahaya nyata dalam mengindeks toobanyak kolom adalah memperlambat perubahan pada baris dalam tabel besar, karena semua indeks juga perlu diperbarui. Jika Anda benar-benar tidak yakin apa yang harus diindeks, cukup atur kueri Anda yang paling lambat, lihat kolom apa yang paling sering digunakan, dan indeks. Kemudian lihat seberapa cepat mereka.

Eevee
sumber
1

Tipe data numerik yang diurutkan dalam urutan menaik atau menurun adalah indeks yang bagus karena berbagai alasan. Pertama, bilangan umumnya lebih cepat dievaluasi daripada string (varchar, char, nvarchar, dll). Kedua, jika nilai Anda tidak diurutkan, baris dan / atau halaman mungkin perlu diacak untuk memperbarui indeks Anda. Itu biaya tambahan.

Jika Anda menggunakan SQL Server 2005 dan mulai menggunakan uniqueidentifier (guids), dan TIDAK memerlukannya untuk bersifat acak, lihat jenis pengidentifikasi unik berurutan.

Terakhir, jika Anda berbicara tentang indeks berkerumun, Anda sedang berbicara tentang jenis data fisik. Jika Anda memiliki string sebagai indeks berkerumun Anda, itu bisa menjadi jelek.

Ian Suttle
sumber
0

Ini akan lebih cepat jika Anda menggunakan GUID. Misalkan Anda memiliki catatan

  1. 100
  2. 200
  3. 3000
  4. ....

Jika Anda memiliki indeks (pencarian biner, Anda dapat menemukan lokasi fisik rekaman yang Anda cari dalam waktu O (lg n), daripada mencari waktu O (n) secara berurutan. Ini karena Anda tidak tahu rekaman apa yang Anda miliki di meja Anda.

Milhous
sumber
0

Indeks terbaik bergantung pada isi tabel dan apa yang ingin Anda capai.

Diambil contoh database anggota dengan Primary Key of the Members Social Security Numnber. Kami memilih SS karena aplikasi priamry mengacu pada individu dengan cara ini, tetapi Anda juga ingin membuat fungsi pencarian yang akan menggunakan nama depan dan belakang anggota. Saya kemudian akan menyarankan untuk membuat indeks di atas dua bidang tersebut.

Anda harus terlebih dahulu mencari tahu data apa yang akan Anda kueri dan kemudian menentukan data mana yang perlu diindeks.

Joseph
sumber