Trong bài viết cuối cùng của mình, tôi đã bắt đầu phác thảo quy trình mà tôi phải trải qua khi điều chỉnh các truy vấn - cụ thể là khi tôi phát hiện ra rằng tôi cần thêm chỉ mục mới hoặc sửa đổi chỉ mục hiện có. Cho đến thời điểm này, chúng tôi đã xác định được truy vấn có vấn đề, chỉ mục tôi cần, những chỉ mục nào hiện đang tồn tại trên bảng và liệu những chỉ mục đó có đang được sử dụng hay không. Khi chúng tôi có dữ liệu đó, chúng tôi có thể chuyển sang các bước tiếp theo trong quy trình.
Bước 5:Cái gì sử dụng chỉ mục
Ngoài việc xem tần suất sử dụng một chỉ mục (hoặc không), còn có lợi khi biết truy vấn nào sử dụng một chỉ mục, đặc biệt nếu tôi đang tìm cách hợp nhất nó với một chỉ mục khác. May mắn thay, Jonathan Kehayias đã viết một truy vấn để giúp xác định kế hoạch nào sử dụng một chỉ mục cụ thể. Phiên bản của anh ấy có thể được sử dụng cho bộ nhớ cache của kế hoạch - thách thức duy nhất ở đó là thông tin chỉ là tạm thời, vì vậy bạn có thể không nắm bắt được mọi truy vấn sử dụng một chỉ mục cụ thể. Cửa hàng truy vấn có thể trợ giúp điều đó - Tôi đã sửa đổi truy vấn của anh ấy để có được thông tin tương tự từ các gói trong Cửa hàng truy vấn:
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);
Cần lưu ý rằng đây là một điểm khác mà tôi có thể thấy mình ở rất sâu trong lỗ thỏ, tùy thuộc vào số lượng chỉ mục mà tôi đang xem xét và số lượng truy vấn sử dụng chúng. Nếu có thể, tôi cũng sẽ xem xét số lượng thực thi (từ Cửa hàng truy vấn hoặc bộ nhớ cache của gói) để không chỉ hiểu cái gì truy vấn sử dụng một chỉ mục, nhưng tần suất thực thi truy vấn đó. Đây là nơi mà việc điều chỉnh chỉ mục trở thành một nghệ thuật. Tôi có thể thu thập một lượng lớn dữ liệu ... nhưng tôi không có thời gian vô hạn để phân tích, vì vậy tôi phải đưa ra phán đoán về số lượng truy vấn mà tôi sẽ xem xét.
Bước 6:Kiểm tra
Nói một cách đơn giản nhất, kiểm tra chỉ mục có nghĩa là thực hiện truy vấn có vấn đề và thu thập dữ liệu kế hoạch và hiệu suất (thời lượng, IO, CPU, v.v.), sau đó tạo chỉ mục, chạy lại truy vấn và nắm bắt cùng một thông tin. Nếu hiệu suất được cải thiện, bạn nên bắt đầu!
Nó hiếm khi đơn giản như vậy.
Để bắt đầu, tôi thường có ít nhất hai biến thể của một chỉ mục mà tôi muốn kiểm tra, đôi khi nhiều hơn. Tôi bắt đầu với đường cơ sở của mình, sau đó tôi tạo tất cả các biến thể chỉ mục, xóa bộ nhớ cache của kế hoạch và xem SQL Server chọn những gì. Sau đó, tôi lướt qua và buộc từng chỉ mục với một gợi ý, nắm bắt kế hoạch và số liệu hiệu suất cho mỗi lần thực hiện. Lưu ý:điều này giả sử rằng tôi có đủ dung lượng đĩa cho tất cả các chỉ mục… nếu không, thì tôi tạo chúng lần lượt và kiểm tra. Cuối cùng, tôi so sánh các con số. Nếu tôi chỉ thêm một chỉ mục mới, tôi gần như đã hoàn thành. Nhưng nếu tôi đang sửa đổi một chỉ mục hoặc hợp nhất một vài chỉ mục với nhau, nó có thể trở nên phức tạp.
Trong một thế giới lý tưởng, nếu tôi sửa đổi chỉ mục hiện có, tôi sẽ tìm thấy các truy vấn thường xuyên / quan trọng nhất sử dụng chỉ mục hiện tại và nhận các kế hoạch và chỉ số hiệu suất của chúng (điều này rất dễ dàng với Query Store). Sau đó, tôi thay đổi chỉ mục, chạy lại tất cả các truy vấn đó và xem liệu tôi có nhận được những thay đổi đáng kể về hình dạng kế hoạch và / hoặc hiệu suất hay không.
Nếu tôi hợp nhất hai chỉ mục, tôi làm điều tương tự, nhưng với tất cả các truy vấn sử dụng một trong hai chỉ mục và sau đó kiểm tra lại với chỉ mục đã hợp nhất.
Nếu tôi đang thêm / thay đổi / hợp nhất nhiều chỉ mục cho một bảng, thì tôi cần nhận tất cả các truy vấn có liên quan cũng như các kế hoạch và chỉ số của chúng, thay đổi các chỉ mục, sau đó lấy lại tất cả thông tin và so sánh. Điều này có thể cực kỳ tốn thời gian, tùy thuộc vào số lượng truy vấn khác nhau ở đó. Đây là một hình thức nghệ thuật và bạn phải xác định có bao nhiêu truy vấn mà bạn thực sự cần để kiểm tra. Đó là một hàm của tần suất thực thi, mức độ quan trọng / mức độ liên quan của truy vấn và thời gian tôi có sẵn / được phân bổ.
Cuối cùng, nếu tôi thêm chỉ mục vào một bảng và không xóa bất kỳ chỉ mục nào hiện có, thì tôi đã thêm chi phí cho CHÈN, XÓA và có khả năng CẬP NHẬT. Kiểm tra hiệu suất thay đổi này là có thể, nhưng bạn cần một môi trường kiểm tra và khả năng chạy kiểm tra tải và nắm bắt các chỉ số trước và sau thay đổi liên quan đến thời lượng, IO và CPU.
Đó là rất nhiều bạn bè, đó là lý do tại sao thật trớ trêu khi ban đầu tôi nghĩ về việc nói rằng việc điều chỉnh chỉ mục rất dễ dàng. Nó có thể không phải lúc nào cũng đơn giản, nhưng nó có thể. Đó là vấn đề của sự siêng năng và theo dõi tất cả.
Bước 7:Thực hiện
Sau khi tôi kiểm tra (các) chỉ mục mới nhiều nhất có thể, chúng tôi đã sẵn sàng cho việc sản xuất. Tôi thừa nhận rằng tôi xem những thay đổi chỉ số là rủi ro thấp, đặc biệt là những thay đổi mới. Nếu đó là sự cố, bạn có thể loại bỏ nó ngay lập tức và hoàn nguyên về trạng thái ban đầu. Với kịch bản sửa đổi / hợp nhất / thả, bạn muốn mọi thứ được viết theo kịch bản, vì vậy bạn có thể thay đổi và tạo lại các chỉ mục khi cần thiết để đặt lại các chỉ mục. Tôi luôn khuyên bạn nên tắt chỉ mục ban đầu thay vì bỏ chúng, vì sau đó bạn không phải lo lắng về định nghĩa - nếu bạn cần thêm chỉ mục trở lại, bạn chỉ cần xây dựng lại nó.
Tóm tắt
Phương pháp thêm và / hoặc hợp nhất chỉ mục của bạn có thể khác! Cũng giống như điều chỉnh truy vấn, không có quy trình hoàn hảo. Đối với bất kỳ ai mới sử dụng điều chỉnh chỉ mục, điều này hy vọng sẽ cung cấp một phần khởi động các mục cần xem xét và những cân nhắc quan trọng. Không thể thêm chỉ mục mà không thêm một số chi phí - và một lần nữa, đây là lúc nghệ thuật đi vào:bạn phải xác định xem lợi ích của chỉ mục có lớn hơn chi phí sửa đổi của nó hay không.
Điều chỉnh chỉ mục là một quá trình lặp đi lặp lại vĩnh viễn - Tôi không nghĩ rằng bạn đã hoàn thành công việc này vì các thay đổi mã, các bảng hoặc chức năng mới được thêm vào và dữ liệu trong các bảng thay đổi. Kimberly có hai bài đăng (https://www.sqlskills.com/blogs/kimberly/spring-cleaner-your-indexes-part-i/ và https://www.sqlskills.com/blogs/kimberly/spring-cleaner- your-indexes-part-ii /) nói về việc dọn dẹp các chỉ mục của bạn - bây giờ là lúc tốt nhất để bắt đầu! Và cuối cùng, bất cứ khi nào ai đó hỏi, "nên có bao nhiêu chỉ mục cho một bảng?" Tôi trả lời đại loại như, "số lượng ít nhất bạn cần để đáp ứng nhiều truy vấn nhất có thể." Không có con số kỳ diệu nào - tôi đã thấy các bảng có chỉ số bằng 0 và tôi đã thấy các bảng có hơn 100 (tôi chắc chắn rằng một số bạn đã thấy số lượng cao hơn). Không phải số 0 và số 100 đều không tốt, nhưng con số "phù hợp" là con số bạn phải tìm ra bằng cách sử dụng dữ liệu có sẵn và kinh nghiệm của bạn.