Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Pendekatan untuk penyetelan indeks – Bagian 2

Dalam posting terakhir saya, saya mulai menguraikan proses yang saya lalui saat menyetel kueri - khususnya ketika saya menemukan bahwa saya perlu menambahkan indeks baru, atau memodifikasi yang sudah ada. Sampai saat ini kami telah mengidentifikasi kueri yang bermasalah, indeks yang saya butuhkan, indeks apa yang saat ini ada di tabel, dan apakah indeks tersebut sedang digunakan atau tidak. Setelah kami memiliki data tersebut, kami dapat melanjutkan ke langkah selanjutnya dalam proses.

Langkah 5:Apa yang Menggunakan Indeks

Selain melihat seberapa sering indeks digunakan (atau tidak), ada baiknya mengetahui kueri apa gunakan indeks, terutama jika saya ingin menggabungkannya dengan indeks lain. Untungnya, Jonathan Kehayias telah menulis kueri untuk membantu mengidentifikasi paket mana yang menggunakan indeks tertentu. Versinya dapat digunakan untuk cache rencana – satu-satunya tantangan di sana adalah informasinya bersifat sementara, jadi Anda mungkin tidak menangkap setiap kueri yang menggunakan indeks tertentu. Toko Kueri dapat membantu dengan itu – Saya telah memodifikasi kuerinya untuk mendapatkan informasi yang sama dari paket di Toko Kueri:

  SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
  DECLARE @IndexName AS NVARCHAR(128) = N'[IX_Sales_OrderLines_AllocatedStockItems]',
          @lb AS nchar(1) = N'[', @rb AS nchar(1) = N']';
 
  -- Make sure the name passed is appropriately quoted
  IF (LEFT(@IndexName, 1) <> @lb AND RIGHT(@IndexName, 1) <> @rb) SET @IndexName = QUOTENAME(@IndexName);
 
  --Handle the case where the left or right was quoted manually but not the opposite side
  IF LEFT(@IndexName, 1)  <> @lb SET @IndexName = @rb + @IndexName;
  IF RIGHT(@IndexName, 1) <> @rb SET @IndexName = @IndexName + @rb;
 
  ;WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')   
  SELECT
    stmt.value('(@StatementText)[1]', 'varchar(max)') AS SQL_Text,
    obj.value('(@Database)[1]', 'varchar(128)') AS DatabaseName,
    obj.value('(@Schema)[1]', 'varchar(128)') AS SchemaName,
    obj.value('(@Table)[1]', 'varchar(128)') AS TableName,
    obj.value('(@Index)[1]', 'varchar(128)') AS IndexName,
    obj.value('(@IndexKind)[1]', 'varchar(128)') AS IndexKind,
    query_plan
  FROM 	
  (
    SELECT query_plan
    FROM
    (
      SELECT TRY_CONVERT(XML, [qsp].[query_plan]) AS [query_plan]
      FROM sys.query_store_plan [qsp]
    ) tp
  ) AS tab (query_plan)
  CROSS APPLY query_plan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple') AS batch(stmt)
  CROSS APPLY stmt.nodes('.//IndexScan/Object[@Index=sql:variable("@IndexName")]') AS idx(obj)
  OPTION(MAXDOP 1, RECOMPILE);

Perlu dicatat bahwa ini adalah titik lain di mana saya dapat menemukan diri saya sangat dalam di lubang kelinci, tergantung pada jumlah indeks yang saya ulas dan jumlah kueri yang menggunakannya. Jika memungkinkan, saya juga akan mempertimbangkan jumlah eksekusi (dari Query Store atau cache paket) untuk tidak hanya memahami apa kueri menggunakan indeks, tetapi seberapa sering kueri itu dieksekusi. Di sinilah penyetelan indeks menjadi seni. Saya dapat mengumpulkan jumlah data yang tidak masuk akal… tetapi saya tidak memiliki waktu yang tak terbatas untuk menganalisis, jadi saya harus membuat keputusan tentang berapa banyak kueri yang akan saya tinjau.

Langkah 6:Pengujian

Paling sederhana, menguji indeks berarti mengambil kueri yang bermasalah dan menangkap rencana dan data kinerja (durasi, IO, CPU, dll.), lalu membuat indeks, menjalankan kembali kueri, dan menangkap informasi yang sama. Jika kinerja meningkat, Anda siap melakukannya!

Jarang sesederhana itu.

Untuk memulainya, saya sering memiliki setidaknya dua variasi indeks yang ingin saya uji, terkadang lebih. Saya mulai dengan garis dasar saya, lalu saya membuat semua variasi indeks, menghapus cache rencana, dan melihat apa yang dipilih SQL Server. Kemudian saya menelusuri dan memaksa setiap indeks dengan petunjuk, menangkap rencana dan metrik kinerja untuk setiap eksekusi. Catatan:ini mengasumsikan saya memiliki cukup ruang disk untuk semua indeks... jika tidak, maka saya membuatnya satu per satu, dan mengujinya. Akhirnya, saya membandingkan angka-angkanya. Jika saya baru saja menambahkan indeks baru, saya hampir selesai. Tetapi jika saya memodifikasi indeks atau menggabungkan beberapa, itu bisa menjadi rumit.

Di dunia yang ideal, jika saya memodifikasi indeks yang ada, saya menemukan kueri paling sering/penting yang menggunakan indeks saat ini dan mendapatkan rencana dan metrik kinerja mereka (ini mudah dengan Query Store). Kemudian saya mengubah indeks, menjalankan semua kueri itu lagi, dan melihat apakah saya mendapatkan perubahan signifikan dalam bentuk dan/atau kinerja rencana.

Jika saya menggabungkan dua indeks, saya melakukan hal yang sama, tetapi dengan semua kueri yang menggunakan salah satu indeks, lalu menguji ulang dengan indeks gabungan.

Jika saya menambahkan/mengubah/menggabungkan beberapa indeks untuk sebuah tabel, maka saya perlu mendapatkan semua kueri yang relevan dan rencana serta metriknya, mengubah indeks, lalu mendapatkan semua informasi lagi dan membandingkannya. Ini bisa sangat memakan waktu, tergantung pada berapa banyak kueri yang berbeda di sana. Di sinilah bentuk seni dan Anda harus menentukan berapa banyak kueri yang benar-benar perlu Anda uji. Ini adalah fungsi dari frekuensi eksekusi, kepentingan/relevansi kueri, dan waktu yang saya sediakan/alokasikan.

Terakhir, jika saya menambahkan indeks ke tabel, dan saya tidak menghapus yang sudah ada, maka saya telah menambahkan overhead untuk INSERT, DELETE, dan berpotensi UPDATE. Pengujian kinerja perubahan ini dimungkinkan, tetapi Anda memerlukan lingkungan pengujian dan kemampuan untuk menjalankan pengujian beban dan menangkap metrik sebelum dan sesudah perubahan yang terkait dengan durasi, IO, dan CPU.

Banyak teman, itulah mengapa ironis bahwa saya awalnya berpikir untuk menyatakan bahwa penyetelan indeks itu mudah. Ini mungkin tidak selalu sederhana, tetapi itu mungkin. Ini masalah ketekunan dan melacak semuanya.

Langkah 7:Penerapan

Setelah saya memeriksa indeks baru sebanyak mungkin, kami siap untuk produksi. Saya akui bahwa saya melihat perubahan indeks sebagai risiko rendah, terutama yang baru. Jika itu masalah, Anda dapat segera menjatuhkannya, dan kembali ke keadaan semula. Dengan skenario modifikasi/gabungkan/jatuhkan, Anda ingin semuanya skrip, sehingga Anda dapat mengubah dan membuat ulang indeks sesuai kebutuhan untuk mengatur ulang indeks. Saya selalu menyarankan awalnya untuk menonaktifkan indeks daripada menjatuhkannya, karena Anda tidak perlu khawatir tentang definisinya – jika Anda perlu menambahkan kembali indeks, Anda cukup membangunnya kembali.

Ringkasan

Metode Anda untuk menambahkan dan/atau mengkonsolidasikan indeks mungkin berbeda! Sama seperti penyetelan kueri, tidak ada proses yang sempurna. Bagi siapa pun yang baru mengenal penyetelan indeks, semoga ini memberikan permulaan item untuk ditinjau dan pertimbangan penting. Tidak mungkin menambahkan indeks tanpa menambahkan sejumlah biaya tambahan – dan sekali lagi di sinilah seninya:Anda harus menentukan apakah manfaat indeks lebih besar daripada biaya modifikasinya.

Penyetelan indeks adalah proses yang terus-menerus dan berulang – saya rasa Anda belum pernah selesai, karena perubahan kode, tabel atau fungsionalitas baru ditambahkan, dan data dalam tabel berubah. Kimberly memiliki dua pos (https://www.sqlskills.com/blogs/kimberly/spring-cleaning-your-indexes-part-i/ dan https://www.sqlskills.com/blogs/kimberly/spring-cleaning- your-indexes-part-ii/) yang membahas tentang membersihkan indeks Anda — sekarang adalah waktu yang tepat untuk memulai! Dan akhirnya, setiap kali seseorang bertanya, “berapa banyak indeks yang harus ada untuk sebuah tabel?” Saya menjawab dengan sesuatu seperti, "jumlah paling sedikit yang Anda butuhkan untuk memenuhi sebanyak mungkin pertanyaan." Tidak ada angka ajaib — Saya telah melihat tabel dengan indeks nol, dan saya telah melihat tabel dengan lebih dari 100 (saya yakin beberapa dari Anda telah melihat jumlah yang lebih tinggi). Baik nol maupun 100 tidak bagus, tetapi angka yang “benar” adalah angka yang harus Anda ketahui menggunakan data yang tersedia dan pengalaman Anda.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bersenang-senang dengan kompresi (penyimpanan kolom) di atas meja yang sangat besar – bagian 2

  2. T-SQL Selasa #67 :Pencadangan dan Pemulihan Baru Acara yang Diperpanjang

  3. Server Tertaut Salesforce.com dan sp_columns_ex

  4. Menghapus jejak default – Bagian 1

  5. Pengenalan Pola Baris dalam SQL