Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Thiếu chỉ mục trong MS SQL hoặc Tối ưu hóa nhanh chóng

Khi thực hiện một truy vấn, trình tối ưu hóa SQL Server cố gắng tìm kế hoạch truy vấn tốt nhất dựa trên các chỉ mục hiện có và số liệu thống kê mới nhất có sẵn trong một thời gian hợp lý, tất nhiên, nếu kế hoạch này chưa được lưu trữ trong bộ đệm ẩn của máy chủ. Nếu không, truy vấn được thực thi theo kế hoạch này và kế hoạch được lưu trữ trong bộ đệm ẩn của máy chủ. Nếu kế hoạch đã được xây dựng cho truy vấn này, truy vấn sẽ được thực thi theo kế hoạch hiện có.

Chúng tôi quan tâm đến vấn đề sau:

Trong quá trình biên dịch kế hoạch truy vấn, khi sắp xếp các chỉ mục có thể có, nếu máy chủ không tìm thấy chỉ mục tốt nhất, chỉ mục bị thiếu sẽ được đánh dấu trong kế hoạch truy vấn và máy chủ giữ thống kê về các chỉ mục đó:máy chủ sẽ sử dụng chỉ mục này bao nhiêu lần và chi phí truy vấn này là bao nhiêu.

Trong bài viết này, chúng tôi sẽ phân tích các chỉ mục bị thiếu này - cách xử lý chúng.

Hãy xem xét điều này trên một ví dụ cụ thể. Tạo một vài bảng trong cơ sở dữ liệu của chúng tôi trên máy chủ cục bộ và máy chủ thử nghiệm:

[expand title =”Code”]

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

[/ mở rộng]

Cấu trúc đơn giản và bao gồm hai bảng. Bảng đầu tiên được gọi là đơn đặt hàng với các trường như số nhận dạng, ngày bán và người bán. Cái thứ hai là chi tiết đơn hàng, trong đó một số hàng hóa được chỉ định với giá cả và số lượng.

Xem xét một truy vấn đơn giản và kế hoạch của nó:

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

where d.cost > 1800

go

Chúng ta có thể thấy gợi ý màu xanh lá cây về chỉ mục bị thiếu trên màn hình đồ họa của kế hoạch truy vấn. Nếu bạn nhấp chuột phải vào nó và chọn “Thiếu chi tiết chỉ mục ..”, sẽ có văn bản của chỉ mục được đề xuất. Điều duy nhất cần làm là xóa các bình luận trong văn bản và đặt tên cho chỉ mục. Tập lệnh đã sẵn sàng để được thực thi.

Chúng tôi sẽ không xây dựng chỉ mục mà chúng tôi nhận được từ gợi ý do SSMS cung cấp. Thay vào đó, chúng tôi sẽ xem liệu chỉ mục này có được đề xuất bởi các chế độ xem động được liên kết với các chỉ mục bị thiếu hay không. Các chế độ xem như sau:

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

Như chúng ta có thể thấy, có một số thống kê về các chỉ mục bị thiếu trong chế độ xem đầu tiên:

  1. Tìm kiếm sẽ được thực hiện bao nhiêu lần nếu chỉ mục đề xuất tồn tại?
  2. Quá trình quét sẽ được thực hiện bao nhiêu lần nếu chỉ mục được đề xuất tồn tại?
  3. Ngày và giờ mới nhất mà chúng tôi sử dụng chỉ mục
  4. Chi phí thực hiện tại của kế hoạch truy vấn không có chỉ mục được đề xuất.

Chế độ xem thứ hai là nội dung chỉ mục:

  1. Cơ sở dữ liệu
  2. Đối tượng / bảng
  3. Các cột được sắp xếp
  4. Các cột được thêm vào để tăng mức độ phù hợp của chỉ mục

Chế độ xem thứ ba là sự kết hợp của chế độ xem thứ nhất và thứ hai.

Do đó, không khó để có được một script tạo script để tạo các chỉ mục còn thiếu từ các khung nhìn động này. Tập lệnh như sau:

[expand title =”Code”]

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

[/ mở rộng]

Đối với hiệu quả của chỉ mục, các chỉ mục bị thiếu sẽ được xuất ra. Giải pháp hoàn hảo là khi tập kết quả này không trả về kết quả nào. Trong ví dụ của chúng tôi, tập kết quả sẽ trả về ít nhất một chỉ mục:

Khi không có thời gian và bạn không muốn xử lý các lỗi máy khách, tôi đã thực hiện truy vấn, sao chép cột đầu tiên và thực thi nó trên máy chủ. Sau đó, mọi thứ hoạt động tốt.

Tôi khuyên bạn nên xử lý thông tin trên các chỉ mục này một cách có ý thức. Ví dụ:nếu hệ thống đề xuất các chỉ mục sau:

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)

Và các chỉ mục này được sử dụng cho việc tìm kiếm, rõ ràng là hợp lý hơn khi thay thế các chỉ mục này bằng một chỉ mục sẽ bao gồm cả ba đề xuất:

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

Do đó, chúng tôi thực hiện xem xét các chỉ mục còn thiếu trước khi triển khai chúng cho máy chủ sản xuất. Mặc du…. Một lần nữa, ví dụ:tôi đã triển khai các chỉ mục bị mất tới máy chủ TFS, do đó, làm tăng hiệu suất tổng thể. Phải mất thời gian tối thiểu để thực hiện tối ưu hóa này. Tuy nhiên, khi chuyển từ TFS 2015 sang TFS 2017, tôi gặp phải vấn đề là không có bản cập nhật do các chỉ số mới này. Tuy nhiên, có thể dễ dàng tìm thấy chúng bằng mặt nạ

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

Công cụ hữu ích:

dbForge Index Manager - phần bổ trợ SSMS tiện dụng để phân tích trạng thái của chỉ mục SQL và khắc phục sự cố với phân mảnh chỉ mục.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL DROP TABLE cho người mới bắt đầu

  2. Di chuyển dữ liệu

  3. Vui vẻ với nén (columnstore) trên một bàn rất lớn - phần 2

  4. NoSQL:Cuộc sống không có lược đồ

  5. Một lý do khác để tránh sp_updatestats