Chỉ mục trong SQL Server giúp tăng tốc độ truy vấn bằng cách giảm lượng dữ liệu cần quét. Tuy nhiên, mỗi thao tác INSERT, UPDATE hoặc DELETE đều yêu cầu hệ thống đồng bộ lại các chỉ mục liên quan — điều này tiêu tốn CPU, I/O và bộ nhớ. Một chỉ mục hiếm khi được dùng để tra cứu (user_seeks = 0) nhưng lại bị cập nhật hàng chục nghìn lần sẽ trở thành "gánh nặng vô hình", chiếm dung lượng đĩa và làm chậm hiệu năng tổng thể.
Dưới đây là hai kịch bản phân tích thực tế, được viết lại với cấu trúc rõ ràng, tên biến mang tính mô tả cao và logic tối ưu hơn:
1. Tổng quan chỉ mục theo cơ sở dữ liệu
Truy vấn sau liệt kê toàn bộ chỉ mục trong cơ sở dữ liệu vims_sc, kèm số lần tra cứu, quét, thời điểm sử dụng gần nhất và số dòng trong bảng tương ứng:
USE vims_sc;
WITH index_usage AS (
SELECT
DB_NAME(ius.database_id) AS database_name,
OBJECT_NAME(ius.object_id) AS table_name,
i.name AS index_name,
ius.user_seeks AS seek_count,
ius.user_scans AS scan_count,
ius.user_lookups AS lookup_count,
ius.last_user_seek AS last_seek_time,
ius.last_user_scan AS last_scan_time,
p.rows AS total_rows
FROM sys.dm_db_index_usage_stats ius
INNER JOIN sys.indexes i
ON ius.object_id = i.object_id AND ius.index_id = i.index_id
INNER JOIN sys.partitions p
ON i.object_id = p.object_id AND i.index_id = p.index_id AND p.index_id < 2
WHERE ius.database_id = DB_ID()
AND OBJECTPROPERTY(ius.object_id, 'IsUserTable') = 1
AND i.is_disabled = 0
AND i.type IN (1, 2) -- clustered & nonclustered only
)
SELECT *
FROM index_usage
WHERE table_name = 'AP_VC_Vaccine'
ORDER BY seek_count ASC, scan_count ASC;
2. Đánh giá chi tiết chỉ mục trên một bảng cụ thể
Đối với bảng StockOut, truy vấn sau cung cấp thông tin về mức độ khai thác từng chỉ mục, đồng thời sinh lệnh DROP INDEX tự động cho những chỉ mục không hiệu quả:
SELECT TOP 100
t.name AS table_name,
i.name AS index_name,
i.index_id,
ius.user_seeks,
ius.user_scans,
ius.user_lookups,
ius.user_updates,
p.rows AS row_count,
CONCAT(
'DROP INDEX ',
QUOTENAME(i.name),
' ON ',
QUOTENAME(s.name), '.',
QUOTENAME(t.name)
) AS drop_statement
FROM sys.dm_db_index_usage_stats ius
INNER JOIN sys.indexes i
ON ius.object_id = i.object_id AND ius.index_id = i.index_id
INNER JOIN sys.tables t
ON i.object_id = t.object_id
INNER JOIN sys.schemas s
ON t.schema_id = s.schema_id
INNER JOIN sys.partitions p
ON i.object_id = p.object_id AND i.index_id = p.index_id AND p.partition_number = 1
WHERE ius.database_id = DB_ID()
AND t.name = 'StockOut'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
AND i.type IN (1, 2)
ORDER BY (ius.user_seeks + ius.user_scans + ius.user_lookups) ASC;
Lưu ý: Các thống kê trong sys.dm_db_index_usage_stats được reset khi SQL Server khởi động lại hoặc khi cơ sở dữ liệu bị offline/online. Vì vậy, kết quả chỉ phản ánh hành vi truy vấn kể từ lần khởi động gần nhất.