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

Indeks Hilang di MS SQL atau Optimasi dalam waktu singkat

Saat menjalankan kueri, pengoptimal SQL Server mencoba menemukan paket kueri terbaik berdasarkan indeks yang ada dan statistik terbaru yang tersedia untuk waktu yang wajar, tentu saja, jika paket ini belum disimpan di cache server. Jika tidak, kueri dijalankan sesuai dengan rencana ini, dan rencana tersebut disimpan dalam cache server. Jika rencana telah dibuat untuk kueri ini, kueri akan dieksekusi sesuai dengan rencana yang ada.

Kami tertarik dengan masalah berikut:

Selama kompilasi rencana kueri, saat menyortir kemungkinan indeks, jika server tidak menemukan indeks terbaik, indeks yang hilang ditandai dalam rencana kueri, dan server menyimpan statistik pada indeks tersebut:berapa kali server akan menggunakan indeks ini dan berapa biaya kueri ini.

Dalam artikel ini, kita akan menganalisis indeks yang hilang ini – cara mengatasinya.

Mari kita pertimbangkan ini pada contoh tertentu. Buat beberapa tabel di database kami di server lokal dan uji coba:

[expand title =”Kode”]

if object_id ('orders_detail') is not null drop table orders_detail;

if object_id('orders') is not null drop table orders;

go

create table orders

(

id int identity primary key,

dt datetime,

seller nvarchar(50)

)

create table orders_detail

(

id int identity primary key,

order_id int foreign key references orders(id),

product nvarchar(30),

qty int,

price money,

cost as qty * price

)

go

with cte as

(

select 1 id union all

select id+1 from cte where id < 20000

)

insert orders

select

dt,

seller

from

(

select

dateadd(day,abs(convert(int,convert(binary(4),newid()))%365),'2016-01-01') dt,

abs(convert(int,convert(binary(4),newid()))%5)+1 seller_id

from cte

) c

left join

(

values
(1,'John'),

(2,'Mike'),

(3,'Ann'),

(4,'Alice'),

(5,'George')
) t (id,seller) on t.id = c.seller_id

option(maxrecursion 0)

 

insert orders_detail

select

order_id,

product,

qty,

price

from

(

select

o.id as order_id,

abs(convert(int,convert(binary(4),newid()))%5)+1 product_id,

abs(convert(int,convert(binary(4),newid()))%20)+1 qty

from orders o cross join

(

select top(abs(convert(int,convert(binary(4),newid()))%5)+1) *

from

(

values (1),(2),(3),(4),(5),(6),(7),(8)

) n(num)

) n

) c

left join

(

values
(1,'Sugar', 50),

(2,'Milk', 80),

(3,'Bread', 20),

(4,'Pasta', 40),

(5,'Beer', 100)

) t (id,product, price) on t.id = c.product_id

go

[/expand]

Strukturnya sederhana dan terdiri dari dua tabel. Tabel pertama disebut pesanan dengan bidang seperti pengenal, tanggal penjualan, dan penjual. Yang kedua adalah detail pesanan, di mana beberapa barang ditentukan dengan harga dan kuantitas.

Lihat kueri sederhana dan rencananya:

select count(*) from orders o join orders_detail d on o.id = d.order_id

where d.cost > 1800

go

Kita dapat melihat petunjuk hijau tentang indeks yang hilang pada tampilan grafik dari rencana kueri. Jika Anda mengklik kanan dan memilih "Rincian Indeks yang Hilang ..", akan ada teks indeks yang disarankan. Satu-satunya hal yang harus dilakukan adalah menghapus komentar dalam teks dan memberi nama pada index. Script siap dieksekusi.

Kami tidak akan membangun indeks yang kami terima dari petunjuk yang diberikan oleh SSMS. Sebagai gantinya, kita akan melihat apakah indeks ini akan direkomendasikan oleh tampilan dinamis yang ditautkan ke indeks yang hilang. Tampilannya adalah sebagai berikut:

select * from sys.dm_db_missing_index_group_stats

select * from sys.dm_db_missing_index_details

select * from sys.dm_db_missing_index_groups

Seperti yang bisa kita lihat, ada beberapa statistik tentang indeks yang hilang pada tampilan pertama:

  1. Berapa kali pencarian akan dilakukan jika indeks yang disarankan ada?
  2. Berapa kali pemindaian akan dilakukan jika indeks yang disarankan ada?
  3. Tanggal dan waktu terakhir kami menggunakan indeks
  4. Biaya sebenarnya dari paket kueri saat ini tanpa indeks yang disarankan.

Tampilan kedua adalah badan indeks:

  1. Basis Data
  2. Objek/tabel
  3. Kolom yang diurutkan
  4. Kolom ditambahkan untuk meningkatkan cakupan indeks

Tampilan ketiga adalah kombinasi dari tampilan pertama dan kedua.

Oleh karena itu, tidaklah sulit untuk mendapatkan skrip yang akan menghasilkan skrip untuk membuat indeks yang hilang dari tampilan dinamis ini. Scriptnya adalah sebagai berikut:

[expand title="Kode"]

with igs as

(

select *

from sys.dm_db_missing_index_group_stats

)

, igd as

(

select *,

isnull(equality_columns,'')+','+isnull(inequality_columns,'') as ix_col

from sys.dm_db_missing_index_details

)

select --top(10)

'use ['+db_name(igd.database_id)+'];

create index ['+'ix_'+replace(convert(varchar(10),getdate(),120),'-','')+'_'+convert(varchar,igs.group_handle)+'] on '+

igd.[statement]+'('+

case

when left(ix_col,1)=',' then stuff(ix_col,1,1,'')

when right(ix_col,1)=',' then reverse(stuff(reverse(ix_col),1,1,''))

else ix_col

end

+') '+isnull('include('+igd.included_columns+')','')+' with(online=on, maxdop=0)

go

' command

,igs.user_seeks

,igs.user_scans

,igs.avg_total_user_cost

from igs

join sys.dm_db_missing_index_groups link on link.index_group_handle = igs.group_handle

join igd on link.index_handle = igd.index_handle

where igd.database_id = db_id()

order by igs.avg_total_user_cost * igs.user_seeks desc

[/expand]

Untuk efisiensi indeks, indeks yang hilang adalah output. Solusi sempurna adalah ketika set hasil ini tidak menghasilkan apa-apa. Dalam contoh kita, kumpulan hasil akan mengembalikan setidaknya satu indeks:

Ketika tidak ada waktu dan Anda tidak ingin berurusan dengan bug klien, saya menjalankan kueri, menyalin kolom pertama dan mengeksekusinya di server. Setelah ini, semuanya bekerja dengan baik.

Saya sarankan memperlakukan informasi pada indeks ini secara sadar. Misalnya, jika sistem merekomendasikan indeks berikut:

create index ix_01 on tbl1 (a,b) include (c)

create index ix_02 on tbl1 (a,b) include (d)

create index ix_03 on tbl1 (a)

Dan indeks-indeks ini digunakan untuk pencarian, cukup jelas bahwa lebih logis untuk mengganti indeks-indeks ini dengan indeks yang mencakup ketiganya yang disarankan:

create index ix_1 on tbl1 (a,b) include (c,d)

Oleh karena itu, kami meninjau indeks yang hilang sebelum menerapkannya ke server produksi. Meskipun…. Sekali lagi, misalnya, saya menyebarkan indeks yang hilang ke server TFS, sehingga meningkatkan kinerja secara keseluruhan. Butuh waktu minimum untuk melakukan pengoptimalan ini. Namun, ketika mengubah dari TFS 2015 ke TFS 2017, saya menghadapi masalah bahwa tidak ada pembaruan karena indeks baru ini. Namun demikian, mereka dapat dengan mudah ditemukan dengan topeng

select * from sys.indexes where name like 'ix[_]2017%'

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. Notasi UML

  2. Cara Memberi Peringkat Baris Dalam Partisi di SQL

  3. Ambang Pengoptimalan – Pengelompokan dan Penggabungan Data, Bagian 4

  4. Pelajari cara menggunakan SQL SELECT dengan contoh

  5. Cara Menulis Query dengan Beberapa Perilaku