Lưu ý:Bài đăng này ban đầu chỉ được xuất bản trong sách điện tử của chúng tôi, Kỹ thuật hiệu suất cao cho SQL Server, Tập 3. Bạn có thể tìm hiểu về sách điện tử của chúng tôi tại đây.
Hơn ba năm trước, tôi đã viết một bài về các tùy chọn con trỏ trong SQL Server và tại sao bạn nên ghi đè các giá trị mặc định:
- Các tùy chọn con trỏ khác nhau có thể có tác động gì?
Tôi muốn đăng một bài tiếp theo để nhắc lại rằng - trong khi bạn không bao giờ nên chỉ chấp nhận các giá trị mặc định - thì bạn thực sự nên suy nghĩ về những tùy chọn nào phù hợp nhất với tình huống của bạn. Tôi cũng muốn làm rõ một số mục xuất hiện trong các nhận xét trên bài đăng đó.
Andrew Kelly đã đưa ra một điểm tuyệt vời và đó là STATIC
con trỏ tạo một bản sao kết quả một lần, đưa chúng vào tempdb và sau đó tránh mọi sự cố đồng thời có thể ảnh hưởng đến DYNAMIC
con trỏ. Trong mọi trường hợp, một lựa chọn không phải là lựa chọn chiến thắng rõ ràng so với lựa chọn còn lại; ví dụ:bạn có thể có rất nhiều con trỏ (hoặc con trỏ có tập kết quả rất lớn) và / hoặc một tempdb đã quá tải và không muốn giảm tải thêm bất kỳ căng thẳng nào ở đó. Nhưng nó là thứ đáng để thử nghiệm.
Fabiano cũng đưa ra một điểm tuyệt vời mà cả DYNAMIC
và FAST_FORWARD
con trỏ có thể dễ bị ảnh hưởng bởi vấn đề Hallowe'en (được Paul White thảo luận trong loạt bài 4 phần, bắt đầu từ đây). Paul cũng nhận xét rằng FAST_FORWARD
có thể không dễ gặp sự cố, tùy thuộc vào việc trình tối ưu hóa chọn phương án tĩnh hay động (Marc Friedman của Microsoft sẽ trình bày chi tiết về điều đó tại đây).
Cuối cùng, tôi muốn chỉ ra rằng không phải tất cả các con trỏ mặc định đều được tạo ra như nhau. Tôi đã chạy một số thử nghiệm và kiểm tra cách SQL Server quyết định đặt các tùy chọn con trỏ trong nhiều trường hợp khác nhau (được xác thực bằng cách sử dụng sys.dm_exec_cursors
chức năng quản lý động). Mã này khá đơn giản:
DECLARE c CURSOR FOR [...blah blah...]; SELECT properties FROM sys.dm_exec_cursors(@@SPID);
Dưới đây là kết quả cho các tình huống tôi đã thử nghiệm:
Truy vấn con trỏ dựa trên… | Loại | Đồng thời | Phạm vi |
---|---|---|---|
một hằng số (FOR SELECT 1 hoặc FOR SELECT SYSDATETIME() ) | Ảnh chụp nhanh | Chỉ đọc | Toàn cầu |
a #temp / ## bảng tạm thời | Động | Lạc quan | Toàn cầu |
một bảng / chế độ xem người dùng | Động | Lạc quan | Toàn cầu |
chế độ xem danh mục / DMV | Ảnh chụp nhanh | Chỉ đọc | Toàn cầu |
a join #tmp -> user table / view | Động | Lạc quan | Toàn cầu |
a tham gia #tmp -> xem danh mục / DMV | Ảnh chụp nhanh | Chỉ đọc | Toàn cầu |
một bảng người dùng tham gia / chế độ xem -> chế độ xem danh mục / DMV | Ảnh chụp nhanh | Chỉ đọc | Toàn cầu |
Ghi có khi đến hạn trả - cuộc điều tra này được thực hiện bởi câu trả lời từ Jeroen Mostert trên Stack Overflow.
Vì vậy, bạn nên biết rằng các tùy chọn mặc định cho con trỏ của bạn, nếu bạn không ghi đè chúng, có thể khác nhau tùy thuộc vào truy vấn bên dưới con trỏ. Nếu bạn đang mong đợi một hành vi cụ thể trong bất kỳ hoặc tất cả các trường hợp, hãy tập thói quen chỉ định rõ ràng các tùy chọn bạn muốn.
Nhưng thực sự, vấn đề là…
… Ngừng sử dụng con trỏ. Thực sự có rất ít vấn đề ngày nay trong đó giải pháp tốt nhất là con trỏ, đặc biệt nếu bạn đang sử dụng SQL Server 2012 trở lên - nơi mà hầu như mọi vấn đề truyền thống được giải quyết bằng con trỏ đều có thể được giải quyết bằng cách sử dụng các cải tiến cho các chức năng cửa sổ. Nếu bạn vẫn cảm thấy mình cần sử dụng con trỏ, vui lòng tham khảo lời khuyên trong bài đăng này và bài đăng trước của nó để xác định tùy chọn nào bạn nên sử dụng.