Pengindeksan dari awal atau ketika masalah kinerja muncul?

15

Pertanyaan saya adalah tentang penggunaan indeks.

  1. Haruskah saya mulai mengindeks langsung dari awal atau ketika masalah kinerja muncul?

  2. Kami juga dapat membuat indeks sementara saat menjalankan kueri. Apa pro dan kontra dari teknik seperti itu?

codecool
sumber

Jawaban:

17

Haruskah saya mulai mengindeks langsung dari awal atau ketika masalah kinerja muncul?

Strategi pengindeksan cenderung berevolusi ketika pola penggunaan muncul. Yang mengatakan, ada juga strategi dan pedoman desain yang dapat diterapkan di muka.

  • Pilih kunci pengelompokan yang baik . Anda biasanya dapat menentukan indeks berkerumun yang sesuai pada waktu desain, berdasarkan pola yang diharapkan dari sebuah tabel. Jika kasus yang mendesak muncul untuk perubahan di masa depan, maka jadilah itu.

  • Buat batasan utama dan unik lainnya . Ini akan diberlakukan oleh indeks unik.

  • Buat kunci asing Anda dan indeks non-cluster yang terkait . Kunci asing adalah kolom gabungan yang paling sering Anda referensikan, jadi buatlah indeks dari awal.

  • Buat indeks untuk kueri yang sangat selektif . Untuk pola kueri yang sudah Anda ketahui akan sangat selektif dan cenderung menggunakan pencarian daripada pemindaian.

Di luar hal di atas, lakukan pendekatan bertahap dan holistik untuk menerapkan indeks baru. Secara holistik, maksud saya menilai potensi manfaat dan dampak terhadap semua pertanyaan dan indeks yang ada saat mengevaluasi penambahan.

Masalah yang tidak biasa dalam lingkaran SQL Server adalah overindexing, sebagai hasil bimbingan dari DMV indeks yang hilang dan petunjuk SSMS. Tak satu pun dari alat ini yang mengevaluasi indeks yang ada dan dengan senang hati akan menyarankan Anda membuat indeks 6 kolom baru daripada menambahkan satu kolom ke indeks 5 kolom yang ada.

-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
)

-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

Kimberly Tripp memiliki beberapa bahan yang sangat baik tentang strategi pengindeksan yang sementara SQL fokus berlaku untuk platform lain. Untuk rakyat SQL Server, ada beberapa alat praktis untuk mengidentifikasi duplikat seperti contoh di atas.

Kami juga dapat membuat indeks sementara saat menjalankan kueri. Apa pro dan kontra dari teknik seperti itu?

Ini biasanya hanya berlaku untuk kueri yang jarang dijalankan, biasanya ETL. Anda perlu menilai:

  1. Apakah waktu yang diperlukan untuk membuat indeks mengurangi waktu eksekusi permintaan.
  2. Apakah pemeliharaan overhead meninggalkan indeks di tempat lebih penting daripada waktu yang dibutuhkan untuk membuat / drop ketika itu diperlukan.
Mark Storey-Smith
sumber
3
+1 Clustering Key, Foreign Key, Unique / Primary Key, dan tidak mempercayai DMV indeks yang hilang pada nilai nominal ... Semua hal ini merupakan saran yang bagus. Berurusan dengan indeks yang ada, di SQL Server, cukup mudah untuk dipantau menggunakan sys.dm_db_index_usage_stats DMV. Selama periode waktu tertentu, Anda dapat membuat daftar indeks yang belum dipindai atau dicari, sambil juga melihat bahwa indeks yang sama ini telah diperbarui beberapa kali. Ini merupakan indikasi overindexing.
Matt M
1
+1, namun 'buat indeks untuk kueri yang sangat selektif.' tidak mencakup semua skenario lainnya. Indeks dapat membantu menyortir hasil bahkan jika kueri Anda tidak sangat selektif. Mereka juga dapat mempercepat permintaan jika mereka mencakup semua kolom yang dipilih.
masuk akal
1
Setuju, tetapi pertanyaannya adalah mencari titik awal daripada akhir permainan. Mengidentifikasi kueri untuk dicakup sulit tanpa pola penggunaan karena Anda jarang bisa membahas semuanya.
Mark Storey-Smith
8

Benar-benar ada risiko yang terkait dengan kedua pendekatan:

Opsi a) Indeks dari awal, tetapi tidak sadar Anda telah membuat sejumlah indeks yang tidak pernah digunakan. Ini menambahkan beberapa overhead (paling jelas untuk query yang memodifikasi data, tetapi juga dengan optimasi pernyataan SELECT mencoba mengidentifikasi indeks terbaik).

Anda perlu mendisiplinkan diri Anda untuk mengidentifikasi indeks yang tidak lagi digunakan dan mencoba dan menghapusnya (PostgreSQL dapat melakukan ini; sayangnya MySQL dengan perbandingan sangat lemah saat ini di luar kotak.)

Opsi b) Jangan menambahkan indeks sampai orang-orang mulai mengeluh, atau alat diagnostik Anda memicu bahwa permintaan tertentu lambat dan dapat ditingkatkan.

Risiko yang Anda perkenalkan adalah Anda tidak memiliki jendela waktu yang cukup besar antara saat Anda melihat Anda membutuhkan indeks, dan ketika Anda harus menambahkannya.

PostgreSQL mendukung indeks bangunan CONCURRENTLY, yang memang mengurangi sebagian tekanan dari persyaratan indeks-mendadak ini, tetapi ada beberapa peringatan yang dicatat dalam manual.


Opsi (b) cenderung menjadi pilihan saya, tetapi saya pikir gabungan dari kedua opsi tersebut mungkin merupakan solusi terbaik. Ini berkaitan dengan tingkat kepercayaan Anda, apakah Anda berpikir indeks akan benar-benar digunakan.

Apa yang membuat diskusi ini sangat kompleks adalah bahwa biasanya mudah untuk mengubah indeks, tetapi lebih sulit untuk mengubah skema. Saya tidak ingin mempromosikan reaksi b yang tertunda sebagai alasan untuk gegabah.

Morgan Tocker
sumber
4

Selain jawaban Markus

Anda bisa merasakannya dengan memiliki data tes realistis pada jumlah yang diharapkan. Saya telah melihat banyak, banyak (terlalu banyak) kasus di mana kueri berjalan OK dengan 1000 baris tetapi tidak dalam jutaan produksi.

Jika Anda bisa, kerjakan salinan produksi nanti,

Tentu saja, saya telah melihat masalah aneh hanya dalam produksi karena pola penggunaan ketika yang lainnya identik

Indeks sementara? Di luar pola muat ETL, jika Anda membutuhkannya sekali Anda akan membutuhkannya lagi. Jangan lupa: indeks buat / letakkan adalah tulisan dan dicatat = muat lebih banyak

gbn
sumber
3

Hanya dengan menambahkan beberapa hal.

  • Indeks sementara adalah ide yang buruk .. kecuali indeks berada di tabel temp.
  • Indeks mengambil lebih banyak ruang data (serta overhead lainnya) daripada yang disadari orang. Karena itu, buat mereka secara konservatif.

Ini pendekatan saya.

  1. Mirip dengan Mark, buat indeks di tempat yang masuk akal, tetapi jangan sampai terlambat.
  2. Anda tidak perlu menunggu sampai kinerja lambat untuk membuat indeks baru. Setiap kali Anda menulis SQL baru, jalankan rencana kueri (lebih disukai terhadap basis data produk Anda). Anda harus dapat melihat apakah indeks baru diperlukan.
  3. Jangan takut untuk meletakkan > 0atau > ""di mana klausa Anda untuk kolom yang tidak digunakan.

    1. Yaitu, katakanlah Anda memiliki indeks pada A, B, C, dan D. Namun, Anda hanya memiliki informasi A, B, D. Tidak ada alasan Anda tidak bisa melakukan-
    select * from blah 
    where A="one" 
    and B="two" 
    and C>=""     --to match index
    and D="four"
    
    --This will use your existing index. No need to create a redundant one.
pengguna606723
sumber
Hal lain, ini ada di forum "dba", tetapi pembuatan indeks harus benar-benar menjadi tanggung jawab pengembang, bukan tanggung jawab dba. (Untuk kasus di mana mereka benar-benar terpisah.)
user606723
2
Pernyataan Anda tentang ruang yang diambil oleh indeks sedikit menyesatkan, ada sangat sedikit overhead dalam indeks non-cluster. Jika Anda dapat memposting pertanyaan tentang hal itu, ada baiknya ditelusuri lebih lanjut. Kedua, saya tidak setuju bahwa pembuatan indeks adalah domain pengembang. Ini sangat banyak salah satu bidang di mana kolaborasi antara pengembang dan DBA dapat menghasilkan hasil terbaik.
Mark Storey-Smith
1
Saya akan memberi Anda contoh dari salah satu tabel kami. ukuran tabel: 21052404 KB. Ukuran satu indeks non-cluster pada tabel ini: 6637470 KB. Sangat sedikit overhead? Saya pikir tidak. Lebih jauh, saya tidak mengatakan bahwa DBA tidak boleh dikolaborasikan dengan, saya mengatakan bahwa itu seharusnya menjadi tanggung jawab pengembang untuk menentukan apakah indeks baru perlu dibuat. Mereka seharusnya tidak menulis SQL dan berharap dBA untuk mencari tahu sendiri.
user606723
1
Anda tidak dapat mengutip angka seperti itu tanpa konteks. Tanpa menentukan kolom indeks NC dan kunci berkerumun, tidak mungkin untuk menghitung proporsi data overhead vs.
Mark Storey-Smith
Sentuh. Kuncinya adalah [numerik (24), karakter, tanggal] dan kolom NC adalah [tanggal, angka (24)]. (Hanya dua kolom dalam indeks khusus ini).
user606723
2

Saya akan mencoba menjawab hanya pertanyaan pertama. Jika Anda dapat memperkirakan bahkan secara kasar dari awal berapa banyak catatan yang akan Anda miliki di tabel setelah jangka waktu tertentu, daripada saya katakan lebih baik mulai dari awal untuk merancang beberapa indeks. Coba gunakan beberapa alat uji atau skrip pengujian yang akan mengotomatiskan sebanyak mungkin panggilan untuk panggilan aplikasi yang menurut Anda paling sering digunakan dan Anda akan melihat pemindaian tabel apa yang dapat dihindari sejak awal.

Ini akan menjadi pekerjaan tebakan di awal, tetapi seiring waktu, karena Anda memiliki statistik penggunaan yang tepat, Anda akan memiliki gambar yang lebih jelas.

Marian
sumber