Tại sao lỗi truy vấn với kết quả trống được đặt trong SQL Server 2012?


31

Khi chạy các truy vấn sau trong MS SQL Server 2012, truy vấn thứ hai không thành công nhưng không phải là truy vấn đầu tiên. Ngoài ra, khi chạy mà không có mệnh đề, cả hai truy vấn sẽ thất bại. Tôi thua lỗ tại sao một trong hai sẽ thất bại vì cả hai nên có tập kết quả trống. Bất kỳ trợ giúp / cái nhìn sâu sắc được đánh giá cao.

create table #temp
(id     int primary key)

create table #temp2
(id     int)

select 1/0
from #temp
where id = 1

select 1/0
from #temp2
where id = 1

Câu trả lời:


39

Một cái nhìn ban đầu về các kế hoạch thực hiện cho thấy biểu thức 1/0được xác định trong các toán tử vô hướng tính toán:

Kế hoạch đồ họa

Bây giờ, mặc dù các kế hoạch thực hiện bắt đầu thực hiện ở phía bên trái, nhưng việc gọi lặp lại OpenGetRowcác phương thức trên các trình lặp con để trả về kết quả, SQL Server 2005 và sau đó chứa một tối ưu hóa theo đó các biểu thức thường chỉ được xác định bởi Compute Scalar, với việc đánh giá bị trì hoãn cho đến lần tiếp theo hoạt động đòi hỏi kết quả :

Tính toán toán tử vô hướng xuất hiện trong Showplans được tạo bởi SET STATISTICS XML có thể không chứa phần tử RunTimeInform.  Trong Showplans đồ họa, Hàng thực tế, Rebinds thực tế và Tua lại thực tế có thể vắng mặt trong cửa sổ Thuộc tính khi tùy chọn Bao gồm Kế hoạch thực thi thực tế được chọn trong SQL Server Management Studio.  Khi điều này xảy ra, điều đó có nghĩa là mặc dù các toán tử này đã được sử dụng trong kế hoạch truy vấn đã biên dịch, công việc của chúng được thực hiện bởi các toán tử khác trong kế hoạch truy vấn thời gian chạy.  Cũng lưu ý rằng số lần thực thi trong đầu ra Showplan được tạo bởi SET STATISTICS PROFILE tương đương với tổng số rebinds và tua lại trong Showplans được tạo bởi SET STATISTICS XML.  Từ: Sách MSDN trực tuyến

Trong trường hợp này, kết quả biểu thức chỉ cần thiết khi lắp ráp hàng để trả về máy khách (mà bạn có thể nghĩ là xảy ra ở SELECTbiểu tượng màu xanh lá cây ). Theo logic đó, đánh giá hoãn lại có nghĩa là biểu thức không bao giờ được đánh giá vì không kế hoạch nào tạo ra một hàng trả về. Để giải quyết vấn đề một chút, cả Tìm kiếm chỉ mục cụm và Quét bảng đều trả về một hàng, do đó không có hàng nào để lắp ráp để trả về cho máy khách.

Tuy nhiên, có một tối ưu hóa riêng biệt theo đó một số biểu thức có thể được xác định là hằng số thời gian chạy và do đó được đánh giá một lần trước khi bắt đầu thực hiện truy vấn . Trong trường hợp này, một dấu hiệu này đã xảy ra có thể được tìm thấy trong XML của kế hoạch (Kế hoạch tìm kiếm chỉ mục cụm ở bên trái, kế hoạch quét bảng ở bên phải):

Showplan XML

Tôi đã viết thêm về các cơ chế cơ bản và cách chúng có thể ảnh hưởng đến hiệu suất trong bài đăng trên blog này . Sử dụng thông tin được cung cấp ở đó, chúng tôi có thể sửa đổi truy vấn đầu tiên để cả hai biểu thức được ước tính và lưu vào bộ đệm trước khi bắt đầu thực thi:

select 1/0 * CONVERT(integer, @@DBTS)
from #temp
where id = 1

select 1/0
from #temp2
where id = 1

Bây giờ, kế hoạch đầu tiên cũng chứa một tham chiếu biểu thức không đổi và cả hai truy vấn đều tạo ra thông báo lỗi. XML cho truy vấn đầu tiên chứa:

Biểu hiện liên tục

Thông tin thêm: Tính toán vô hướng, biểu thức và hiệu suất


21

Tôi sẽ đoán một cách thông minh (và trong quá trình có thể thu hút một chuyên gia SQL Server, người có thể đưa ra câu trả lời thực sự chi tiết).

Truy vấn đầu tiên tiếp cận thực thi như:

  1. Quét chỉ mục khóa chính
  2. Tra cứu các giá trị trong bảng dữ liệu cần thiết cho truy vấn

Nó chọn đường dẫn này bởi vì bạn có một wheremệnh đề trên khóa chính. Nó không bao giờ đến bước thứ hai, vì vậy truy vấn không thất bại.

Cái thứ hai không có khóa chính để chạy, vì vậy nó tiếp cận truy vấn như:

  1. Thực hiện quét toàn bộ bảng dữ liệu và truy xuất các giá trị cần thiết

Một trong những giá trị đó đang 1/0gây ra vấn đề.

Đây là một ví dụ về SQL Server tối ưu hóa truy vấn. Đối với hầu hết các phần, đây là một điều tốt. SQL Server sẽ chuyển các điều kiện từ selecthoạt động quét bảng. Điều này thường lưu các bước trong việc đánh giá truy vấn.

Nhưng, tối ưu hóa này không phải là một điều tốt đẹp không được thừa nhận. Trong thực tế, nó dường như vi phạm chính tài liệu SQL Server nói rằng wheremệnh đề này được đánh giá trước select. Chà, họ có thể có một số lời giải thích uyên bác cho điều này có nghĩa là gì. Tuy nhiên, đối với hầu hết mọi người, xử lý một cách hợp lý wheretrước selectnghĩa là (trong số những thứ khác) "không tạo ra các selectlỗi -clew trên các hàng không được trả lại cho người dùng".


1
+1 không có đầu mối nếu bạn đúng, nhưng câu trả lời tốt nhất tôi có thể thấy với sự khác biệt duy nhất là khóa chính.

1
@GordonLinoff Paul Randal vừa xác nhận qua Twitter rằng câu trả lời của bạn đã được thực hiện.
SchmitzIT

4
@Still, thứ tự thực hiện thực tế, tuy nhiên khác nhau, không nên dẫn đến các thông báo lỗi như thế.
ypercubeᵀᴹ

7
@ypercube Erland Sommarskog sẽ đồng ý với bạn (Kết nối mục)
Paul White nói GoFundMonica

2
Cảm ơn bạn đã cho con trỏ - Tôi đã đăng nhập và nâng cấp yêu cầu.
Gordon Linoff
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.