Tôi nghĩ rằng tôi có thể có một lời giải thích một phần cho điều này nhưng xin vui lòng bắn hạ nó hoặc đăng bất kỳ lựa chọn thay thế. @MartinSmith chắc chắn sẽ làm được điều gì đó bằng cách làm nổi bật hiệu quả của TOP trong kế hoạch thực hiện.
Nói một cách đơn giản, 'Đếm hàng thực tế' không phải là tổng số hàng mà toán tử xử lý, nó là số lần phương thức GetNext () của toán tử được gọi.
Lấy từ BOL :
Các toán tử vật lý khởi tạo, thu thập dữ liệu và đóng. Cụ thể, toán tử vật lý có thể trả lời ba cuộc gọi phương thức sau:
- Init (): Phương thức init () làm cho một toán tử vật lý tự khởi tạo và thiết lập bất kỳ cấu trúc dữ liệu cần thiết nào. Toán tử vật lý có thể nhận được nhiều cuộc gọi init (), mặc dù thông thường, một toán tử vật lý chỉ nhận được một cuộc gọi.
- GetNext (): Phương thức GetNext () khiến toán tử vật lý nhận được hàng dữ liệu đầu tiên hoặc tiếp theo. Toán tử vật lý có thể nhận được 0 hoặc nhiều lệnh gọi GetNext ().
- Đóng (): Phương thức Đóng () khiến toán tử vật lý thực hiện một số thao tác dọn dẹp và tự tắt. Một toán tử vật lý chỉ nhận được một cuộc gọi Đóng ().
Phương thức GetNext () trả về một hàng dữ liệu và số lần được gọi là ActualRows trong đầu ra Showplan được tạo bằng cách sử dụng SET STATISTICS PROFILE ON hoặc SET STATISTICS XML ON.
Để hoàn thiện, một chút nền tảng về các toán tử song song là hữu ích. Công việc được phân phối cho nhiều luồng trong một kế hoạch song song bởi luồng phân vùng lại hoặc phân phối các toán tử luồng. Chúng phân phối các hàng hoặc trang giữa các luồng bằng một trong bốn cơ chế:
- Hash phân phối các hàng dựa trên hàm băm của các cột trong hàng
- Vòng tròn phân phối các hàng bằng cách lặp qua danh sách các chuỗi trong một vòng lặp
- Broadcast phân phối tất cả các trang hoặc hàng cho tất cả các chủ đề
- Phân vùng nhu cầu chỉ được sử dụng để quét. Chủ đề quay lên, yêu cầu một trang dữ liệu từ toán tử, xử lý nó và yêu cầu một trang tiếp theo khi hoàn thành.
Toán tử phân phối luồng đầu tiên (hầu hết trong kế hoạch) sử dụng phân vùng nhu cầu trên các hàng có nguồn gốc từ quá trình quét liên tục. Có ba luồng gọi GetNext () 6, 4 và 0 lần với tổng số 10 'Hàng thực tế':
<RunTimeInformation>
<RunTimeCountersPerThread Thread="2" ActualRows="6" ActualEndOfScans="1" ActualExecutions="1" />
<RunTimeCountersPerThread Thread="1" ActualRows="4" ActualEndOfScans="1" ActualExecutions="1" />
<RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
</RunTimeInformation>
Tại toán tử phân phối tiếp theo, chúng ta có ba luồng một lần nữa, lần này với các lệnh gọi 50, 50 và 0 đến GetNext () với tổng số 100:
<RunTimeInformation>
<RunTimeCountersPerThread Thread="2" ActualRows="50" ActualEndOfScans="1" ActualExecutions="1" />
<RunTimeCountersPerThread Thread="1" ActualRows="50" ActualEndOfScans="1" ActualExecutions="1" />
<RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
</RunTimeInformation>
Chính tại toán tử song song tiếp theo, nguyên nhân và lời giải thích có thể xuất hiện.
<RunTimeInformation>
<RunTimeCountersPerThread Thread="2" ActualRows="1" ActualEndOfScans="0" ActualExecutions="1" />
<RunTimeCountersPerThread Thread="1" ActualRows="10" ActualEndOfScans="0" ActualExecutions="1" />
<RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
</RunTimeInformation>
Vì vậy, bây giờ chúng tôi có 11 cuộc gọi đến GetNext (), nơi chúng tôi đang mong đợi để xem 10 cuộc gọi.
Chỉnh sửa: 2011-11-13
Bị mắc kẹt tại thời điểm này, tôi đã đi tìm câu trả lời với các lỗ hổng trong chỉ mục được nhóm và @MikeWalsh vui lòng chỉ dẫn @QueryKiwi tại đây .