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

Bộ chỉ mục háo hức và Trình tối ưu hóa

Giới thiệu

Một Bộ chỉ mục háo hức đọc tất cả các hàng từ toán tử con của nó vào một bảng làm việc được lập chỉ mục, trước khi nó bắt đầu trả về các hàng cho toán tử cha của nó. Theo một số khía cạnh, một cuộn chỉ mục háo hức là gợi ý chỉ mục còn thiếu cuối cùng , nhưng nó không được báo cáo như vậy.

Đánh giá chi phí

Chèn các hàng vào một bảng làm việc được lập chỉ mục có chi phí tương đối thấp, nhưng không miễn phí. Trình tối ưu hóa phải xem xét rằng công việc liên quan tiết kiệm nhiều hơn chi phí. Để điều đó diễn ra có lợi cho ống chỉ, kế hoạch phải được ước tính để tiêu thụ các hàng từ ống chỉ nhiều hơn một lần. Nếu không, nó cũng có thể bỏ qua ống chỉ và chỉ thực hiện thao tác cơ bản một lần.

  • Để được truy cập nhiều lần, ống chỉ phải xuất hiện ở phía bên trong của toán tử tham gia vòng lặp lồng nhau.
  • Mỗi lần lặp lại của vòng lặp phải tìm kiếm một giá trị khóa chỉ mục cụ thể được cung cấp bởi phía bên ngoài của vòng lặp.

Điều đó có nghĩa là tham gia cần phải là một áp dụng , không phải là tham gia các vòng lồng nhau . Để biết sự khác biệt giữa hai loại, vui lòng xem bài viết của tôi Áp dụng so với Tham gia các vòng lặp lồng nhau.

Các tính năng đáng chú ý

Mặc dù ống chỉ mục háo hức có thể chỉ xuất hiện ở phía bên trong của vòng lặp lồng nhau áp dụng , nó không phải là một "ống hiệu suất". Không thể tắt ống chỉ mục háo hức bằng cờ theo dõi 8690 hoặc NO_PERFORMANCE_SPOOL gợi ý truy vấn.

Các hàng được chèn vào ống chỉ mục thường không được sắp xếp trước theo thứ tự khóa chỉ mục, điều này có thể dẫn đến việc tách trang chỉ mục. Cờ theo dõi không có giấy tờ 9260 có thể được sử dụng để tạo Sắp xếp toán tử trước ống chỉ mục để tránh điều này. Nhược điểm là chi phí sắp xếp bổ sung có thể cản trở trình tối ưu hóa chọn tùy chọn cuộn.

SQL Server không hỗ trợ chèn song song vào chỉ mục b-tree. Điều này có nghĩa là mọi thứ bên dưới một ống chỉ mục háo hức song song chạy trên một luồng duy nhất. Các toán tử bên dưới ống chỉ vẫn được đánh dấu (gây hiểu nhầm) bằng biểu tượng song song. Một chuỗi được chọn để viết vào ống chỉ. Các chuỗi khác chờ trên EXECSYNC trong khi điều đó hoàn thành. Khi ống được điền, nó có thể được đọc từ bằng các chủ đề song song.

Các cuộn chỉ mục không cho trình tối ưu hóa biết rằng chúng hỗ trợ đầu ra được sắp xếp theo các khóa chỉ mục của cuộn chỉ mục. Nếu đầu ra được sắp xếp từ cuộn là bắt buộc, bạn có thể thấy thông báo Sắp xếp không cần thiết nhà điều hành. Dù sao thì các cuộn chỉ mục háo hức cũng thường được thay thế bằng một chỉ mục cố định, vì vậy, đây là một vấn đề nhỏ thường xuyên xảy ra.

Có năm quy tắc trình tối ưu hóa có thể tạo Bộ chỉ mục háo hức tùy chọn (được gọi nội bộ là một chỉ mục trực tuyến ). Chúng tôi sẽ xem xét chi tiết ba trong số những thứ này để hiểu được các cuộn chỉ mục háo hức đến từ đâu.

SelToIndexOnTheFly

Đây là một trong những phổ biến nhất. Nó khớp với một hoặc nhiều lựa chọn quan hệ (còn gọi là bộ lọc hoặc vị từ) ngay phía trên toán tử truy cập dữ liệu. SelToIndexOnTheFly quy tắc thay thế các vị từ bằng một vị từ tìm kiếm trên một cuộn chỉ mục háo hức.

Demo

An AdventureWorks ví dụ về cơ sở dữ liệu mẫu được hiển thị bên dưới:

SELECT
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel,
    TH.Quantity
FROM Production.Product AS P
CROSS APPLY
(
    SELECT MAX(TH.Quantity)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.ProductID = P.ProductID
        AND TH.Quantity < P.SafetyStockLevel
    GROUP BY ()
) AS TH (Quantity)
WHERE
    P.[Name] LIKE N'A%';

Kế hoạch thực hiện này có chi phí ước tính là 3.0881 các đơn vị. Một số điểm lưu ý:

  • Tham gia bên trong các vòng lặp lồng nhau toán tử là một áp dụng , với ProductIDSafetyStockLevel từ Product bảng dưới dạng tham chiếu bên ngoài .
  • Trong lần lặp đầu tiên của ứng dụng, Bộ chỉ mục háo hức được điền đầy đủ từ Quét chỉ mục theo cụm của TransactionHistory bảng.
  • Bàn làm việc của ống chỉ có một chỉ mục nhóm được khóa trên (ProductID, Quantity) .
  • Các hàng phù hợp với các vị từ TH.ProductID = P.ProductIDTH.Quantity < P.SafetyStockLevel được trả lời bởi ống chỉ sử dụng chỉ mục của nó. Điều này đúng cho mọi lần lặp lại ứng dụng, kể cả lần lặp lại đầu tiên.
  • TransactionHistory bảng chỉ được quét một lần.

Đã sắp xếp đầu vào cho ống chỉ

Có thể thực thi đầu vào được sắp xếp vào cuộn chỉ mục háo hức, nhưng điều này ảnh hưởng đến chi phí ước tính, như đã lưu ý trong phần giới thiệu. Đối với ví dụ ở trên, việc bật cờ theo dõi không có tài liệu sẽ tạo ra một kế hoạch không có cuộn:

SELECT
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel,
    TH.Quantity
FROM Production.Product AS P
CROSS APPLY
(
    SELECT
        MAX(TH.Quantity)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.ProductID = P.ProductID
        AND TH.Quantity < P.SafetyStockLevel
    GROUP BY ()
) AS TH (Quantity)
WHERE
    P.[Name] LIKE N'A%'
OPTION (QUERYTRACEON 9260);

Chi phí ước tính của Tìm kiếm chỉ mục này và Tra cứu khóa kế hoạch là 3.11631 các đơn vị. Con số này cao hơn chi phí của gói chỉ có cuộn chỉ mục, nhưng ít hơn so với gói có cuộn chỉ mục và đầu vào được sắp xếp.

Để xem một kế hoạch với đầu vào được sắp xếp vào cuộn, chúng ta cần tăng số lần lặp vòng lặp dự kiến. Điều này mang lại cho ống chỉ cơ hội hoàn trả chi phí bổ sung của Sắp xếp . Một cách để mở rộng số hàng được mong đợi từ Product bảng là để tạo Name vị từ ít hạn chế hơn:

SELECT
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel,
    TH.Quantity
FROM Production.Product AS P
CROSS APPLY
(
    SELECT
        MAX(TH.Quantity)
    FROM Production.TransactionHistory AS TH
    WHERE 
        TH.ProductID = P.ProductID
        AND TH.Quantity < P.SafetyStockLevel
    GROUP BY ()
) AS TH (Quantity)
WHERE
    P.[Name] LIKE N'[A-P]%'
OPTION (QUERYTRACEON 9260);

Điều này cung cấp cho chúng tôi một kế hoạch thực thi với đầu vào được sắp xếp vào cuộn:

Tham giaToIndexOnTheFly

Quy tắc này biến đổi một liên kết bên trong đến một áp dụng , với một ống chỉ mục háo hức ở phía bên trong. Ít nhất một trong các vị từ nối phải là một bất đẳng thức để quy tắc này được khớp.

Đây là quy tắc chuyên biệt hơn nhiều so với SelToIndexOnTheFly , nhưng ý tưởng thì rất giống nhau. Trong trường hợp này, lựa chọn (vị từ) được chuyển đổi thành tìm kiếm ống chỉ mục được liên kết với phép nối. Sự chuyển đổi từ tham gia thành áp dụng cho phép chuyển vị từ nối từ chính phép nối vào phía bên trong của ứng dụng.

Bản trình diễn

SELECT
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel,
    Quantity = MAX(TH.Quantity)
FROM Production.Product AS P
JOIN Production.TransactionHistory AS TH
    ON TH.ProductID = P.ProductID
    AND TH.Quantity < P.SafetyStockLevel
WHERE
    P.[Name] LIKE N'[A-P]%'
GROUP BY
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel
OPTION (LOOP JOIN);

Như trước đây, chúng tôi có thể yêu cầu đầu vào được sắp xếp vào cuộn:

SELECT
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel,
    Quantity = MAX(TH.Quantity)
FROM Production.Product AS P
JOIN Production.TransactionHistory AS TH
    ON TH.ProductID = P.ProductID
    AND TH.Quantity < P.SafetyStockLevel
WHERE
    P.[Name] LIKE N'[A-P]%'
GROUP BY
    P.ProductID,
    P.[Name],
    P.SafetyStockLevel
OPTION (LOOP JOIN, QUERYTRACEON 9260);

Lần này, chi phí sắp xếp bổ sung đã khuyến khích trình tối ưu hóa chọn một gói song song.

Một tác dụng phụ không mong muốn là Sắp xếp toán tử tràn sang tempdb . Tổng bộ nhớ cấp sẵn có để sắp xếp là đủ, nhưng nó được chia đều giữa các luồng song song (như thường lệ). Như đã lưu ý trong phần giới thiệu, SQL Server không hỗ trợ chèn song song vào chỉ mục b-tree, vì vậy các toán tử bên dưới ống chỉ mục háo hức chạy trên một luồng duy nhất. Chuỗi đơn này chỉ nhận được một phần nhỏ của bộ nhớ được cấp, vì vậy Sắp xếp tràn sang tempdb .

Tác dụng phụ này có lẽ là một lý do khiến cờ theo dõi không có tài liệu và không được hỗ trợ.

SelSTVFToIdxOnFly

Quy tắc này thực hiện tương tự như SelToIndexOnTheFly , nhưng đối với chức năng có giá trị bảng trực tuyến (sTVF) nguồn hàng. Các sTVF này được sử dụng rộng rãi trong nội bộ để triển khai các DMV và DMF cùng những thứ khác. Chúng xuất hiện trong các kế hoạch thực thi hiện đại dưới dạng Hàm có giá trị bảng toán tử (ban đầu là quét bảng từ xa ).

Trước đây, nhiều sTVF này không thể chấp nhận các thông số tương quan từ một áp dụng. Họ có thể chấp nhận các ký tự, biến và tham số mô-đun, chỉ không áp dụng tài liệu tham khảo bên ngoài. Vẫn có những cảnh báo về điều này trong tài liệu, nhưng chúng đã lỗi thời.

Dù sao, vấn đề là đôi khi SQL Server không thể vượt qua áp dụng tham chiếu bên ngoài làm tham số cho sTVF. Trong tình huống đó, có thể hợp lý hóa một phần của sTVF dẫn đến một ống chỉ mục háo hức. Quy tắc hiện tại cung cấp khả năng đó.

Bản trình diễn

Ví dụ mã tiếp theo cho thấy một truy vấn DMV được chuyển đổi thành công từ một kết hợp thành một áp dụng . Tài liệu tham khảo bên ngoài được chuyển dưới dạng tham số cho DMV thứ hai:

-- Transformed to an apply
-- Outer reference passed as a parameter
SELECT
    DES.session_id,
    DES.login_time,
    DESWS.waiting_tasks_count
FROM sys.dm_exec_sessions AS DES
JOIN sys.dm_exec_session_wait_stats AS DESWS
    ON DESWS.session_id = DES.session_id
OPTION (FORCE ORDER);

Thuộc tính kế hoạch của thống kê chờ TVF hiển thị các thông số đầu vào. Giá trị tham số thứ hai được cung cấp dưới dạng tham chiếu bên ngoài từ phiên DMV:

Thật tiếc khi sys.dm_exec_session_wait_stats là một chế độ xem chứ không phải một hàm, vì điều đó ngăn cản chúng tôi viết một áp dụng trực tiếp.

Phần viết lại bên dưới đủ để đánh bại chuyển đổi nội bộ:

-- Rewrite to avoid TVF parameter trickery
SELECT
    DES.session_id,
    DES.login_time,
    DESWS.waiting_tasks_count
FROM sys.dm_exec_sessions AS DES
JOIN sys.dm_exec_session_wait_stats AS DESWS
    ON DESWS.session_id >= DES.session_id
    AND DESWS.session_id <= DES.session_id
OPTION (FORCE ORDER);

Với session_id các biến vị ngữ hiện không được sử dụng dưới dạng tham số, SelSTVFToIdxOnFly quy tắc miễn phí để chuyển đổi chúng thành một cuộn chỉ mục háo hức:

Tôi không muốn để lại cho bạn ấn tượng rằng cần phải viết lại phức tạp để có được một cuộn chỉ mục háo hức qua nguồn DMV - nó chỉ giúp cho bản trình diễn dễ dàng hơn. Nếu bạn tình cờ gặp một truy vấn với các phép tham gia DMV tạo ra một kế hoạch với một cuộn mong muốn, ít nhất bạn biết cách nó đến đó.

Bạn không thể tạo chỉ mục trên DMV, vì vậy, bạn có thể cần sử dụng phép băm hoặc phép hợp nhất nếu kế hoạch thực thi không hoạt động đủ tốt.

CTE đệ quy

Hai quy tắc còn lại là SelIterToIdxOnFlyJoinIterToIdxOnFly . Chúng là đối tác trực tiếp của SelToIndexOnTheFlyJoinToIndexOnTheFly cho các nguồn dữ liệu CTE đệ quy. Đây là những điều cực kỳ hiếm theo kinh nghiệm của tôi, vì vậy tôi sẽ không cung cấp bản trình diễn cho chúng. (Chính vì vậy Iter một phần của tên quy tắc có ý nghĩa:Nó xuất phát từ thực tế là SQL Server triển khai đệ quy đuôi dưới dạng lặp lồng nhau.)

Khi một CTE đệ quy được tham chiếu nhiều lần ở bên trong áp dụng, một quy tắc khác (SpoolOnIterator ) có thể lưu vào bộ nhớ cache kết quả của CTE:

WITH R AS
(
    SELECT 1 AS n 
    UNION ALL
    SELECT R.n + 1 
    FROM R 
    WHERE R.n < 10
)
SELECT
    R1.n
FROM R AS R1
CROSS JOIN R AS R2;

Kế hoạch thực hiện có Ống đếm hàng háo hức hiếm gặp :

Kết luận

Các cuộn chỉ mục háo hức thường là một dấu hiệu cho thấy một chỉ mục vĩnh viễn hữu ích bị thiếu trong lược đồ cơ sở dữ liệu. Điều này không phải lúc nào cũng đúng như các ví dụ về hàm có giá trị trong bảng truyền trực tuyến cho thấy.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sự kiện và Chủ đề trong .NET

  2. Quét đơn hàng phân bổ

  3. Tạo bảng mới trong IRI Workbench

  4. Chuyển đổi ngầm bên cột đắt như thế nào?

  5. Mang theo đám mây của riêng bạn có sẵn cho DigitalOcean