Khi kế hoạch thực thi bao gồm quá trình quét cấu trúc chỉ mục b-tree, công cụ lưu trữ có thể có thể chọn giữa hai chiến lược truy cập vật lý khi kế hoạch được thực thi:
- Tuân theo cấu trúc b-cây chỉ mục; hoặc,
- định vị các trang bằng cách sử dụng thông tin phân bổ trang nội bộ.
Khi có sự lựa chọn, công cụ lưu trữ sẽ đưa ra quyết định về thời gian chạy cho mỗi lần thực thi. Bản tổng hợp lại kế hoạch không cần thiết để nó thay đổi ý định.
Chiến lược cây b bắt đầu từ gốc của cây, đi xuống đến mép cực của mức lá (tùy thuộc vào việc quét tiến hay lùi), sau đó đi theo các liên kết trang cấp lá cho đến khi đạt đến đầu kia của chỉ mục . Chiến lược phân bổ sử dụng cấu trúc Bản đồ phân bổ chỉ mục (IAM) để định vị các trang cơ sở dữ liệu được phân bổ cho chỉ mục. Mỗi trang IAM ánh xạ phân bổ đến khoảng 4GB trong một tệp cơ sở dữ liệu vật lý, vì vậy việc quét chuỗi IAM được liên kết với chỉ mục có xu hướng truy cập các trang chỉ mục theo thứ tự tệp vật lý (ít nhất là theo như SQL Server có thể cho biết).
Sự khác biệt chính giữa hai chiến lược là:
- Quét b-tree có thể phân phối các hàng tới bộ xử lý truy vấn theo thứ tự khóa chỉ mục; không thể quét theo hướng IAM;
- quá trình quét b-tree có thể không đưa ra các yêu cầu I / O đọc trước lớn nếu các trang chỉ mục tiếp giáp về mặt logic cũng không tiếp giáp về mặt vật lý (ví dụ:do kết quả của việc tách trang trong chỉ mục).
Quét b-tree luôn có sẵn cho một chỉ mục. Các điều kiện thường được trích dẫn để có sẵn các bản quét thứ tự phân bổ là:
- Kế hoạch truy vấn phải cho phép quét chỉ mục không theo thứ tự;
- chỉ mục phải có kích thước ít nhất là 64 trang; và,
- hoặc là
TABLOCK
hoặcNOLOCK
gợi ý phải được chỉ định.
Điều kiện đầu tiên đơn giản có nghĩa là trình tối ưu hóa truy vấn phải đánh dấu quá trình quét bằng Ordered:False
bất động sản. Đánh dấu quét Ordered:False
có nghĩa là kết quả chính xác từ kế hoạch thực thi không yêu cầu quét để trả về các hàng theo thứ tự khóa chỉ mục (mặc dù nó có thể làm như vậy nếu thuận tiện hoặc cần thiết).
Điều kiện thứ hai (kích thước) chỉ áp dụng cho SQL Server 2005 trở lên. Nó phản ánh thực tế là có một khoản chi phí khởi động nhất định để thực hiện quét theo hướng IAM, vì vậy cần có số trang tối thiểu để có thể tiết kiệm được để hoàn trả khoản đầu tư ban đầu. “64 trang” đề cập đến giá trị của data_pages cho IN_ROW_DATA
chỉ đơn vị phân bổ, như được báo cáo trong sys.allocation_units.
Tất nhiên, chỉ có thể có lợi nhuận từ việc quét đơn đặt hàng phân bổ nếu việc cân nhắc đọc trước có thể lớn hơn thực sự đi vào hoạt động, nhưng SQL Server hiện không xem xét yếu tố này. Đặc biệt, nó không tính đến lượng chỉ mục hiện đang ở trong bộ nhớ, cũng như không quan tâm đến mức độ phân mảnh của chỉ mục.
Điều kiện thứ ba có lẽ là mô tả ít hoàn chỉnh nhất trong danh sách. Trên thực tế, gợi ý không bắt buộc , mặc dù chúng có thể được sử dụng để đáp ứng các yêu cầu thực tế:Dữ liệu phải được đảm bảo không thay đổi trong quá trình quét hoặc (gây tranh cãi hơn), chúng tôi phải chỉ ra rằng chúng tôi không quan tâm về các kết quả có khả năng không chính xác, bằng cách thực hiện quét ở mức cách ly không cam kết đã đọc.
Ngay cả với những giải thích rõ ràng này, danh sách các điều kiện để quét theo thứ tự phân bổ vẫn chưa hoàn chỉnh. Có một số lưu ý và ngoại lệ quan trọng mà chúng ta sẽ trình bày ngay sau đây.
Bản trình diễn
Truy vấn sau sử dụng cơ sở dữ liệu mẫu AdventureWorks:
CHECKPOINT; DBCC DROPCLEANBUFFERS; GOSELECT P.BusinessEntityID, P.PersonTypeFROM Person.Person AS P;
Lưu ý rằng bảng Person chứa 3.869 trang. Kế hoạch hậu thực thi (thực tế) như sau (được hiển thị trong SQL Sentry Plan Explorer):
Về các yêu cầu quét thứ tự phân bổ, chúng tôi có cho đến nay:
- Kế hoạch có
Ordered:False
bất động sản; và, - bảng có hơn 64 trang; nhưng,
- chúng tôi đã không làm gì để đảm bảo dữ liệu không thể thay đổi trong quá trình quét. Giả sử phiên của chúng tôi đang sử dụng cam kết đã đọc mặc định mức cô lập, quá trình quét không được thực hiện ở đã đọc không cam kết mức độ cô lập.
Do đó, chúng tôi mong đợi quá trình quét này được thực hiện bằng cách quét cây b thay vì theo hướng IAM. Kết quả truy vấn cho thấy điều này có thể đúng:
Các hàng được trả về theo thứ tự khóa Chỉ mục cụm (bởi BusinessEntityID
). Tôi phải nói rõ rằng thứ tự kết quả này hoàn toàn không được đảm bảo , và không nên dựa vào. Các kết quả có thứ tự chỉ được đảm bảo bởi một ORDER BY
cấp cao nhất thích hợp mệnh đề.
Tuy nhiên, thứ tự đầu ra quan sát được là bằng chứng ngẫu nhiên cho thấy quá trình quét được thực hiện lần này bằng cách tuân theo cấu trúc cây b-chỉ mục được phân cụm. Nếu cần thêm bằng chứng, chúng tôi có thể đính kèm trình gỡ lỗi và xem đường dẫn mã SQL Server đang thực thi trong quá trình quét:
Ngăn xếp cuộc gọi hiển thị rõ ràng quá trình quét theo cây b.
Thêm gợi ý khóa bảng
Bây giờ chúng tôi sửa đổi truy vấn để bao gồm gợi ý khóa bảng:
CHECKPOINT; DBCC DROPCLEANBUFFERS; CHỌN P.BusinessEntityID, P.PersonTypeFROM Person.Person AS P VỚI (TABLOCK);
Ở cấp độ cách ly đã cam kết đọc khóa mặc định, khóa cấp bảng được chia sẻ ngăn chặn bất kỳ sửa đổi đồng thời nào có thể xảy ra đối với dữ liệu. Với tất cả ba điều kiện tiên quyết để quét theo hướng IAM được đáp ứng, bây giờ chúng tôi mong đợi SQL Server sử dụng quét theo thứ tự cấp phát. Kế hoạch thực hiện vẫn giống như trước, vì vậy tôi sẽ không lặp lại nó, nhưng kết quả truy vấn chắc chắn trông khác:
Các kết quả dường như vẫn được sắp xếp theo thứ tự của BusinessEntityID
, nhưng điểm xuất phát (10866) thì khác. Thật vậy, nếu chúng ta cuộn xuống kết quả, chúng ta sẽ sớm gặp các phần rõ ràng là không có thứ tự quan trọng:
Thứ tự một phần là do quá trình quét thứ tự phân bổ xử lý toàn bộ trang chỉ mục tại một thời điểm. Kết quả trong một trang tình cờ được trả về theo thứ tự của khóa chỉ mục, nhưng thứ tự của các trang được quét giờ đã khác. Một lần nữa, tôi nên nhấn mạnh rằng kết quả có thể khác với bạn:không có gì đảm bảo về thứ tự đầu ra, ngay cả trong một trang, mà không có ORDER BY
cấp cao nhất trên truy vấn ban đầu.
Để so sánh với ngăn xếp cuộc gọi được hiển thị trước đó, đây là dấu vết ngăn xếp thu được trong khi Máy chủ SQL đang xử lý truy vấn với TABLOCK
gợi ý:
Tiến xa hơn một chút trong quá trình thực hiện:
Rõ ràng, SQL Server đang thực hiện quét theo thứ tự cấp phát khi khóa bảng được chỉ định. Thật đáng tiếc là không có dấu hiệu nào trong kế hoạch sau thực thi về loại quét nào đã được sử dụng trong thời gian chạy. Xin nhắc lại, kiểu quét do công cụ lưu trữ chọn và có thể thay đổi giữa các lần thực hiện mà không cần biên dịch lại kế hoạch.
Các cách khác để đáp ứng điều kiện thứ ba
Tôi đã nói trước đó để có được một quá trình quét theo hướng IAM, chúng ta cần đảm bảo dữ liệu không thể thay đổi bên dưới quá trình quét trong khi nó đang diễn ra, hoặc chúng ta cần chạy truy vấn ở mức cách ly không cam kết đã đọc. Chúng tôi đã thấy rằng gợi ý khóa bảng khi khóa cách ly cam kết đã đọc là đủ để đáp ứng yêu cầu đầu tiên trong số các yêu cầu đó và dễ dàng cho thấy rằng việc sử dụng NOLOCK/READUNCOMMITTED
gợi ý cũng cho phép quét thứ tự phân bổ với truy vấn demo.
Trên thực tế, có nhiều cách để đáp ứng điều kiện thứ ba, bao gồm:
- Thay đổi chỉ mục để chỉ cho phép khóa bảng;
- làm cho cơ sở dữ liệu ở chế độ chỉ đọc (vì vậy dữ liệu được đảm bảo không thay đổi); hoặc,
- thay đổi phiên mức cô lập thành
READ UNCOMMITTED
.
Tuy nhiên, có nhiều biến thể thú vị hơn về chủ đề này có nghĩa là chúng tôi cần sửa đổi ba điều kiện đã nêu trước đây…
Các mức cách ly của lập phiên bản hàng
Bật tính năng cô lập ảnh chụp nhanh đã cam kết đã đọc (RCSI) trên cơ sở dữ liệu AdventureWorks và chạy thử nghiệm với TABLOCK
gợi ý một lần nữa (tại đọc cam kết cách ly):
Với RCSI đang hoạt động, được sắp xếp theo chỉ mục quét được sử dụng với
TABLOCK
, không phải quét theo thứ tự phân bổ mà chúng ta đã thấy trước đó. Lý do làTABLOCK
gợi ý chỉ định khóa chia sẻ cấp bảng, nhưng với RCSI được bật, không có khóa chia sẻ nào được thực hiện. Nếu không có khóa bảng được chia sẻ, chúng tôi đã không đáp ứng được yêu cầu ngăn các sửa đổi đồng thời đối với dữ liệu trong khi quá trình quét đang diễn ra, vì vậy không thể sử dụng quá trình quét theo thứ tự phân bổ.Tuy nhiên, có thể thực hiện quét theo thứ tự phân bổ khi RCSI được bật. Một cách là sử dụng
TABLOCKX
gợi ý (dành cho cấp bảng độc quyền lock) thay vìTABLOCK
. Chúng tôi cũng có thể giữ lạiTABLOCK
gợi ý và thêm một cái khác nhưREADCOMMITTEDLOCK
hoặcREPEATABLE READ
hoặcSERIALIZABLE
… và như thế. Tất cả những điều này hoạt động bằng cách ngăn chặn khả năng sửa đổi đồng thời bằng cách sử dụng khóa bảng chia sẻ, với cái giá là mất lợi ích của RCSI . Chúng tôi cũng có thể quét theo thứ tự phân bổ bằng cách sử dụngNOLOCK
hoặcREADUNCOMMITTED
gợi ý, tất nhiên.Tình huống trong cách ly ảnh chụp nhanh (SI) rất giống với RCSI và không được khám phá chi tiết vì lý do không gian.
TABLESAMPLE luôn * thực hiện quét thứ tự phân bổ
TABLESAMPLE
mệnh đề là một ngoại lệ thú vị cho nhiều điều chúng ta đã thảo luận cho đến nay.Chỉ định một
TABLESAMPLE
mệnh đề luôn * dẫn đến việc quét thứ tự cấp phát, ngay cả trong RCSI hoặc SI, và thậm chí không có gợi ý. Để làm rõ hơn về nó, quá trình quét thứ tự phân bổ là kết quả của việc sử dụngTABLESAMPLE
giữ lại ngữ nghĩa RCSI / SI - quá trình quét sử dụng các phiên bản hàng và việc đọc không chặn việc ghi (và ngược lại).Điều ngạc nhiên thứ hai là
TABLESAMPLE
luôn * thực hiện quét theo hướng IAM ngay cả khi bảng có ít hơn 64 trang . Điều này có ý nghĩa vì ít nhất tài liệu cũng gợi ý rằngSYSTEM
phương pháp lấy mẫu sử dụng cấu trúc IAM (vì vậy không có lựa chọn nào khác ngoài việc quét theo thứ tự phân bổ):HỆ THỐNG Là một phương pháp lấy mẫu phụ thuộc vào việc thực hiện theo quy định của tiêu chuẩn ISO. Trong SQL Server, đây là phương pháp lấy mẫu duy nhất có sẵn và được áp dụng theo mặc định. SYSTEM áp dụng phương pháp lấy mẫu dựa trên trang trong đó tập hợp các trang ngẫu nhiên từ bảng được chọn cho mẫu và tất cả các hàng trên các trang đó được trả về dưới dạng tập hợp con mẫu.
* Một ngoại lệ xảy ra nếu
ROWS
hoặcPERCENT
đặc điểm kỹ thuật trongTABLESAMPLE
mệnh đề có nghĩa là 100% của bảng. Chỉ định thêmROWS
hơn siêu dữ liệu cho biết hiện có trong bảng cũng sẽ không hoạt động. Sử dụngTABLESAMPLE SYSTEM (100 PERCENT)
hoặc tương đương sẽ không buộc quét đơn đặt hàng.CHECKPOINT; DBCC DROPCLEANBUFFERS; GOSELECT P.BusinessEntityID, P.PersonTypeFROM Person.Person AS P TABLESAMPLE SYSTEM (50 ROWS) REPEATABLE (12345678) --WITH (TABLOCK);Kết quả:
Ảnh hưởng của TÀI KHOẢN ĐẦU VÀ ĐẶT TÀI KHOẢN
Nói tóm lại, cả hai đều không có bất kỳ ảnh hưởng nào đến quyết định sử dụng quét thứ tự phân bổ hay không. Điều này có vẻ đáng ngạc nhiên trong trường hợp "hiển nhiên" rằng ít hơn 64 trang sẽ được quét.
Ví dụ:các truy vấn sau đều sử dụng quét theo hướng IAM để trả về 5 hàng từ một quá trình quét:
CHỌN ĐẦU (5) P.BusinessEntityID, P.PersonTypeFROM Person.Person AS P VỚI (TABLOCK) ĐẶT ROWCOUNT 5; CHỌN P.BusinessEntityID, P.PersonTypeFROM Person.Person AS P VỚI (TABLOCK) ĐẶT ROWCOUNT 0;Kết quả giống nhau cho cả hai:
Điều này có nghĩa là
TOP
vàSET ROWCOUNT
truy vấn có thể gánh chịu chi phí thiết lập quét theo thứ tự phân bổ, ngay cả khi quét ít hơn 64 trang. Trong việc giảm thiểu, các truy vấn TOP phức tạp hơn với các vị từ chọn lọc được đưa vào quá trình quét vẫn có thể được hưởng lợi từ quá trình quét theo thứ tự phân bổ. Nếu quá trình quét phải xử lý 10.000 trang để tìm ra 5 hàng đầu tiên phù hợp, thì quá trình quét theo thứ tự phân bổ vẫn có thể thắng.Ngăn tất cả * quét theo thứ tự phân bổ trong toàn trường hợp
Đây không phải là điều bạn có thể cố ý làm, nhưng có một cài đặt máy chủ sẽ ngăn việc quét theo thứ tự phân bổ cho tất cả * truy vấn của người dùng trong tất cả cơ sở dữ liệu.
Có vẻ như không chắc, cài đặt được đề cập là tùy chọn cấu hình máy chủ ngưỡng con trỏ, có mô tả sau trong Sách Trực tuyến:
Tùy chọn ngưỡng con trỏ chỉ định số hàng trong tập hợp con trỏ mà tại đó tập hợp phím con trỏ được tạo không đồng bộ. Khi con trỏ tạo bộ khóa cho một tập kết quả, trình tối ưu hóa truy vấn ước tính số hàng sẽ được trả về cho tập kết quả đó. Nếu trình tối ưu hóa truy vấn ước tính rằng số lượng hàng trả về lớn hơn ngưỡng này, thì con trỏ được tạo không đồng bộ, cho phép người dùng tìm nạp các hàng từ con trỏ trong khi con trỏ tiếp tục được điền. Nếu không, con trỏ được tạo đồng bộ và truy vấn đợi cho đến khi tất cả các hàng được trả về.
Nếu
cursor threshold
tùy chọn được đặt thành bất kỳ thứ gì khác ngoài –1 (mặc định), sẽ không có quá trình quét thứ tự cấp phát nào xảy ra đối với các truy vấn của người dùng trong bất kỳ cơ sở dữ liệu nào trên phiên bản SQL Server.Nói cách khác, nếu tập hợp con trỏ không đồng bộ được bật, sẽ không có quá trình quét theo hướng IAM nào cho bạn.
* Ngoại lệ là (không phải 100%)
TABLESAMPLE
truy vấn. Các truy vấn nội bộ do hệ thống tạo ra để tạo thống kê và cập nhật thống kê cũng tiếp tục sử dụng tính năng quét theo thứ tự phân bổ.CHECKPOINT; DBCC DROPCLEANBUFFERS; ĐI - CẢNH BÁO! Tắt tính năng quét theo thứ tự phân bổ trên phạm vi rộngEXECUTE sys.sp_configure @configname ='ngưỡng con trỏ', @configvalue =5000; TÁI HÌNH VỚI OVERRIDE; ĐI - Thông thường sẽ dẫn đến việc quét theo thứ tự phân bổ. ngưỡng con trỏ ', @configvalue =-1; CẤU HÌNH LẠI VỚI BÊN NGOÀI;Kết quả (không quét theo thứ tự phân bổ):
Người ta chỉ có thể đoán rằng tập hợp con trỏ không đồng bộ không hoạt động tốt với quét theo thứ tự phân bổ vì một số lý do. Hoàn toàn không mong muốn rằng hạn chế này sẽ ảnh hưởng đến tất cả các truy vấn của người dùng không dùng con trỏ cũng như mặc dù. Có lẽ quá khó để SQL Server phát hiện xem một truy vấn có đang chạy như một phần của con trỏ API được cấp bên ngoài hay không? Ai biết được.
Sẽ rất tuyệt nếu tác dụng phụ này được chính thức ghi nhận ở đâu đó, mặc dù khó có thể biết chính xác nó sẽ đi đến đâu trong Sách trực tuyến. Tôi tự hỏi có bao nhiêu hệ thống sản xuất ngoài kia không sử dụng tính năng quét theo thứ tự phân bổ vì điều này? Có thể không nhiều, nhưng bạn không bao giờ biết.
Để tóm tắt mọi thứ, đây là một bản tóm tắt. Có thể quét theo thứ tự phân bổ nếu:
- Tùy chọn máy chủ
cursor threshold
được đặt thành –1 (mặc định); và- toán tử quét kế hoạch truy vấn có
Ordered:False
bất động sản; và- tổng số data_pages của
IN_ROW_DATA
đơn vị cấp phát tối thiểu là 64; và- một trong hai:
- SQL Server có một đảm bảo có thể chấp nhận được rằng các sửa đổi đồng thời là không thể; hoặc,
- quá trình quét đang chạy ở mức cách ly không cam kết đã đọc.
Bất kể tất cả những điều trên, hãy quét bằng
TABLESAMPLE
mệnh đề luôn sử dụng quét theo thứ tự cấp phát (với một ngoại lệ kỹ thuật được lưu ý trong văn bản chính).