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

Penyimpanan Kueri:Menampilkan Dampak Indeks pada Sisipan

Pengantar

Sudah menjadi rahasia umum di lingkaran basis data bahwa indeks meningkatkan kinerja kueri baik dengan memenuhi kumpulan hasil yang diperlukan seluruhnya (Meliputi Indeks) atau bertindak sebagai pencarian yang dengan mudah mengarahkan Mesin Kueri ke lokasi yang tepat dari kumpulan data yang diperlukan. Namun, seperti yang diketahui oleh DBA berpengalaman, seseorang tidak boleh terlalu antusias membuat indeks di lingkungan OLTP tanpa memahami sifat beban kerja. Menggunakan Query Store di SQL Server 2019 instance (Query Store diperkenalkan di SQL Server 2016), cukup mudah untuk menunjukkan efek indeks pada sisipan.

Sisipkan Tanpa Indeks

Kita mulai dengan memulihkan database Contoh WideWorldImporters dan kemudian membuat salinan file Sales. Tabel faktur menggunakan skrip dalam Daftar 1. Perhatikan bahwa database sampel telah mengaktifkan Penyimpanan Kueri dalam mode baca-tulis.

-- Listing 1 Make a Copy Of Invoices
SELECT * 
INTO [SALES].[INVOICES1] 
FROM [SALES].[INVOICES]  
WHERE 1=2;

Perhatikan bahwa tidak ada indeks sama sekali dalam tabel yang baru saja kita buat. Yang kita miliki hanyalah struktur tabel. Setelah selesai, kami melakukan penyisipan di tabel baru menggunakan data dari induknya seperti yang ditunjukkan pada Listing 2.

-- Listing 2 Populate Invoices1
-- TRUNCATE TABLE [SALES].[INVOICES1]
INSERT INTO [SALES].[INVOICES1] 
SELECT * FROM [SALES].[INVOICES]; 
GO 100

Selama operasi ini, penyimpanan kueri menangkap rencana eksekusi kueri. Gambar 1 menunjukkan secara singkat apa yang terjadi di bawah tenda. Membaca dari kiri ke kanan, kita melihat bahwa SQL Server mengeksekusi penyisipan menggunakan Plan ID 563 – Pemindaian Indeks pada Kunci Utama tabel sumber untuk mengambil data dan kemudian Sisipan Tabel pada tabel tujuan. (Membaca dari kiri ke kanan). Perhatikan bahwa dalam kasus ini, sebagian besar biaya ada di Sisipan Tabel – 99% dari biaya kueri.

Gambar 1 Rencana Eksekusi 563

Gambar 2 Sisipan Tabel di Tujuan

Gbr. 3 Pemindaian Indeks Berkelompok pada Tabel Sumber

Sisipkan Dengan Indeks

Kami kemudian membuat indeks pada tabel tujuan menggunakan DDL di Listing 3. Ketika kami mengulangi pernyataan di Listing 2 setelah memotong tabel tujuan, kami melihat rencana eksekusi yang sedikit berbeda (Plan ID 593 ditunjukkan pada Gambar 4). Kami masih melihat Sisipan Tabel tetapi hanya berkontribusi 58% untuk biaya kueri. Dinamika eksekusi sedikit miring dengan pengenalan semacam dan Sisipan Indeks. Pada dasarnya apa yang terjadi adalah bahwa SQL Server harus memperkenalkan baris yang sesuai pada indeks saat catatan baru diperkenalkan di tabel.

-- LISTING 3 Create Index on Destination Table
CREATE NONCLUSTERED INDEX [IX_Sales_Invoices_ConfirmedDeliveryTime] ON [Sales].[Invoices1]
(
	[ConfirmedDeliveryTime] ASC
)
INCLUDE ( 	[ConfirmedReceivedBy]) 
WITH (PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, SORT_IN_TEMPDB = OFF
, DROP_EXISTING = OFF
, ONLINE = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON) ON [USERDATA]
GO

Gambar. 4 Rencana Eksekusi 593

Melihat Lebih Dalam

Kami dapat memeriksa detail kedua rencana dan melihat bagaimana faktor-faktor baru ini meningkatkan waktu pelaksanaan pernyataan. Paket 593 menambahkan 300 ms tambahan atau lebih ke Durasi Rata-rata pernyataan. Di bawah beban kerja yang berat di lingkungan produksi, perbedaan ini bisa menjadi signifikan.

Mengaktifkan STATISTICS IO saat mengeksekusi pernyataan penyisipan hanya sekali dalam kedua kasus – dengan Indeks pada tabel tujuan dan tanpa indeks pada tabel Tujuan – juga menunjukkan bahwa lebih banyak pekerjaan yang dilakukan dalam hal IO logis saat menyisipkan baris dalam tabel dengan indeks.

Gambar 5 Rincian Rencana Eksekusi 563

Gbr. 4 Rincian Rencana Eksekusi 593

Tidak Ada Indeks:Keluaran dengan STATISTICS IO Dinyalakan:

Tabel 'Faktur1'. Hitungan pindai 0, pembacaan logis 78372 , pembacaan fisik 0, pembacaan depan membaca 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan depan pembacaan lob 0.

Tabel 'Faktur'. Hitungan pindai 1, pembacaan logis 11400, pembacaan fisik 0, pembacaan depan pembacaan 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan depan pembacaan lob 0.

(70510 baris terpengaruh)

Indeks:Keluaran dengan STATISTICS IO Diaktifkan:

Tabel 'Faktur1'. Hitungan pindai 0, pembacaan logis 81119 , pembacaan fisik 0, pembacaan depan membaca 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan depan pembacaan lob 0.

Tabel 'Meja Kerja'. Hitungan pemindaian 0, pembacaan logis 0, pembacaan fisik 0, pembacaan ke depan 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan pembacaan ke depan lob 0.

Tabel 'Faktur'. Hitungan pindai 1, pembacaan logis 11400 , pembacaan fisik 0, pembacaan depan membaca 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan depan pembacaan lob 0.

(70510 baris terpengaruh)

Informasi Tambahan

Microsoft dan sumber lain menyediakan skrip untuk memeriksa lingkungan produksi indeks dan mengidentifikasi situasi seperti:

  1. Indeks Redundan – Indeks yang digandakan
  2. Indeks Tidak Ada – Indeks yang dapat meningkatkan kinerja berdasarkan beban kerja
  3. Tumpukan – Tabel tanpa Indeks Clustered
  4. Tabel yang diindeks berlebihan – Tabel dengan indeks lebih dari kolom
  5. Penggunaan Indeks – Hitungan pencarian, pemindaian, dan pencarian pada indeks

Butir 2, 3, dan 5 lebih terkait dengan dampak kinerja sehubungan dengan membaca, sedangkan butir 1 dan 4 terkait dengan dampak kinerja sehubungan dengan menulis. Daftar 4 dan 5 adalah dua contoh kueri yang tersedia untuk umum ini.

-- LISTING 4 Check Redundant Indexes
;WITH INDEXCOLUMNS AS(
SELECT DISTINCT
SCHEMA_NAME (O.SCHEMA_ID) AS 'SCHEMANAME'
, OBJECT_NAME(O.OBJECT_ID) AS TABLENAME
,I.NAME AS INDEXNAME, O.OBJECT_ID,I.INDEX_ID,I.TYPE
,(SELECT CASE KEY_ORDINAL WHEN 0 THEN NULL ELSE '['+COL_NAME(K.OBJECT_ID,COLUMN_ID) +']' END AS [DATA()]
FROM SYS.INDEX_COLUMNS AS K WHERE K.OBJECT_ID = I.OBJECT_ID AND K.INDEX_ID = I.INDEX_ID
ORDER BY KEY_ORDINAL, COLUMN_ID FOR XML PATH('')) AS COLS
FROM SYS.INDEXES AS I INNER JOIN SYS.OBJECTS O ON I.OBJECT_ID =O.OBJECT_ID 
INNER JOIN SYS.INDEX_COLUMNS IC ON IC.OBJECT_ID =I.OBJECT_ID AND IC.INDEX_ID =I.INDEX_ID
INNER JOIN SYS.COLUMNS C ON C.OBJECT_ID = IC.OBJECT_ID AND C.COLUMN_ID = IC.COLUMN_ID
WHERE I.OBJECT_ID IN (SELECT OBJECT_ID FROM SYS.OBJECTS WHERE TYPE ='U') AND I.INDEX_ID <>0 AND I.TYPE <>3 AND I.TYPE <>6
GROUP BY O.SCHEMA_ID,O.OBJECT_ID,I.OBJECT_ID,I.NAME,I.INDEX_ID,I.TYPE
) 

SELECT 
IC1.SCHEMANAME,IC1.TABLENAME,IC1.INDEXNAME,IC1.COLS AS INDEXCOLS,IC2.INDEXNAME AS REDUNDANTINDEXNAME, IC2.COLS AS REDUNDANTINDEXCOLS
FROM INDEXCOLUMNS IC1
JOIN INDEXCOLUMNS IC2 ON IC1.OBJECT_ID = IC2.OBJECT_ID
AND IC1.INDEX_ID <> IC2.INDEX_ID
AND IC1.COLS <> IC2.COLS
AND IC2.COLS LIKE REPLACE(IC1.COLS,'[','[[]') + ' %'
ORDER BY 1,2,3,5;

-- LISTING 5 Check Indexes Usage
SELECT O.NAME AS TABLE_NAME
, I.NAME AS INDEX_NAME
, S.USER_SEEKS
, S.USER_SCANS
, S.USER_LOOKUPS
, S.USER_UPDATES
FROM SYS.DM_DB_INDEX_USAGE_STATS S
INNER JOIN SYS.INDEXES I
ON I.INDEX_ID=S.INDEX_ID
AND S.OBJECT_ID = I.OBJECT_ID
INNER JOIN SYS.OBJECTS O
ON S.OBJECT_ID = O.OBJECT_ID
INNER JOIN SYS.SCHEMAS C
ON O.SCHEMA_ID = C.SCHEMA_ID;

Kesimpulan

Kami telah menunjukkan, menggunakan Query Store, bahwa beban kerja tambahan dengan indeks dapat diperkenalkan dalam rencana eksekusi pernyataan penyisipan sampel. Dalam produksi, indeks yang berlebihan dan berlebihan dapat berdampak negatif pada kinerja, terutama dalam basis data yang dimaksudkan untuk beban kerja OLTP. Penting untuk menggunakan skrip dan alat yang tersedia untuk memeriksa indeks dan menentukan apakah mereka benar-benar membantu atau mengganggu kinerja.

Alat yang berguna:

dbForge Index Manager – add-in SSMS yang berguna untuk menganalisis status indeks SQL dan memperbaiki masalah dengan fragmentasi indeks.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana Cara Menggunakan Klausa ORDER BY Dalam SQL?

  2. Mengapa Menggunakan Tes Unit adalah Investasi Besar untuk Arsitektur Berkualitas Tinggi

  3. Menjebak Kesalahan Server Tertaut

  4. Apa Perbedaan Antara RANK dan DENSE_RANK dalam SQL?

  5. Parameter Mengendus Primer