Tại sao nhiều hơn (và số lượng khác nhau) đọc hợp lý với đọc trước (tìm nạp trước)?


8

Sau khi tạo cơ sở dữ liệu tpch trong SQL Server của tôi, tôi đã thử truy vấn bên dưới:

    set statistics io on
    DBCC DROPCLEANBUFFERS;        
    select top 100 * from dbo.lineitem order by l_partkey;

Dòng bảng có một chỉ mục không được nhóm trên l_partkey. Tôi đã đưa ra các truy vấn trên một vài lần và phát hiện ra rằng các lần đọc logic khác nhau mỗi lần:

    Table 'lineitem'. Scan count 1, logical reads 1019, physical reads 4, read-ahead reads 1760, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'lineitem'. Scan count 1, logical reads 1007, physical reads 4, read-ahead reads 1720, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'lineitem'. Scan count 1, logical reads 1030, physical reads 4, read-ahead reads 1792, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Từ bài đăng ở đây: Số lượng đọc hợp lý khác nhau , tôi biết nó có thể được gây ra bởi hành vi đọc trước.

NHƯNG chính xác tại sao đọc trước có thể gây ra đọc hợp lý hơn? Làm thế nào để nó thay đổi hành vi SQL Server? Giống như SQL Server có thể đọc thêm trang chỉ mục vì dù sao nó cũng nằm trong bộ đệm?

Dù sao, tôi đã vô hiệu hóa đọc trước và đưa ra truy vấn trên. Bây giờ nó báo cáo cùng một số lần đọc logic mỗi lần. NHƯNG các lần đọc logic nhỏ hơn nhiều !!

    Table 'lineitem'. Scan count 1, logical reads 404, physical reads 160, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Vì vậy, câu hỏi của tôi là, tại sao tính năng đọc trước có thể gây ra nhiều số lần đọc logic hơn và khác nhau?

Vì tò mò, tôi đã thử một truy vấn khác mà không có "order by":

    select top 100 * from dbo.lineitem

Đây là kết quả mà không cần đọc trước:

    Table 'lineitem'. Scan count 1, logical reads 5, physical reads 3, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Đây là kết quả với đọc trước:

    Table 'lineitem'. Scan count 1, logical reads 15, physical reads 2, read-ahead reads 3416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Người đọc trước vẫn có cách đọc hợp lý hơn. Vậy tại sao?

Câu trả lời:


9

Kế hoạch truy vấn cho ORDER BY l_partkeyví dụ gần như chắc chắn đọc chỉ mục không bao gồm theo thứ tự (có đọc trước), theo sau là Tra cứu khóa để truy xuất các cột không được phát hiện.

Toán tử Nested Loops Join phía trên Tra cứu có thể sử dụng thêm tìm nạp trước ( WithOrderedPrefetch) cho Tra cứu. Xem bài viết sau tôi đã viết để biết chi tiết đầy đủ:

Ngoài ra, như tôi đã đề cập trong câu trả lời cho câu hỏi và trả lời được liên kết, số lần đọc trước phụ thuộc vào thời gian và đặc điểm hệ thống lưu trữ. Các loại cân nhắc tương tự áp dụng cho Tra cứu tìm nạp trước tại Vòng lặp lồng nhau Tham gia.

Lưu ý rằng SQL Server phát hành trước các trang thể cần thiết khi quét chỉ mục, nhưng điều này không bị giới hạn bởi TOPđặc tả trong truy vấn. Đây TOPlà một phần tử bộ xử lý truy vấn, trong khi phần đọc phía trước được điều khiển bởi Storage Engine.

Các hoạt động khá riêng biệt: đọc trước (và tìm nạp trước) phát hành I / O không đồng bộ cho các trang thể cần để Quét (hoặc Tra cứu).

Tùy thuộc vào thứ tự thực hiện hoàn thành và cung cấp các hàng cho bộ xử lý truy vấn (trong số những thứ khác), số lượng trang thực sự chạm vào (đọc logic) hoặc đọc vật lý có thể khác nhau. Đặc biệt lưu ý rằng Tra cứu bị trì hoãn tìm nạp trước cũng góp phần vào việc đọc logic khi nó kiểm tra xem liệu một trang cần cho Tra cứu đã có trong bộ nhớ hay chưa.

Vì vậy, tất cả bắt nguồn từ thời gian chi tiết của các hoạt động chồng chéo: Bộ xử lý truy vấn sẽ bắt đầu tắt đường dẫn thực hiện truy vấn ngay khi số lượng hàng (100) yêu cầu được nhìn thấy ở Trình lặp hàng đầu. Khá nhiều I / O không đồng bộ (đọc trước hoặc tìm nạp trước) sẽ được ban hành hoặc hoàn thành tại thời điểm đó về cơ bản là không xác định.

Bạn có thể vô hiệu hóa các vòng lặp lồng nhau Tham gia tìm nạp trước với cờ theo dõi 8744 để khám phá điều này hơn nữa. Điều này sẽ xóa WithOrderedPrefetchtài sản khỏi Vòng lặp Nested Tham gia. Tôi thường sử dụng OPTION (QUERYTRACEON 8744)trên các truy vấn chính nó. Trong mọi trường hợp, bạn cần chắc chắn rằng bạn không sử dụng lại gói được lưu trong bộ nhớ cache có tìm nạp trước. Xóa bộ nhớ cache của gói mỗi lần hoặc buộc biên dịch lại truy vấn OPTION (RECOMPILE).

Đọc logic là một thước đo đơn giản về số lượng trang bộ nhớ cache được chạm vào thay mặt truy vấn. Khi tính năng đọc trước (và / hoặc tìm nạp trước) được bật, nhiều trang chỉ mục và dữ liệu (và khác nhau!) Có thể được chạm để phát hành trước đó hoặc là một phần của hoạt động tìm nạp trước.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.