Có sự khác biệt nào giữa một vị từ sử dụng giá trị bằng chữ hoặc giá trị tham số khi giá trị đó sẽ luôn giống nhau không?


7

Tôi có một truy vấn luôn lọc theo trạng thái, có lợi ích hiệu suất của một trong những cách này so với cách khác không?

(Đây là trong ngữ cảnh của một truy vấn đặc biệt. Kiểu dữ liệu của UserStatus là int)

...
AND UserStatus = 1
...

hoặc là

DECLARE @userStatus int = 1
...
AND UserStatus = @userStatus
...

(ps xin đừng nói về cách các thông số và nghĩa đen khác nhau khi các giá trị không xác định / thay đổi, đó là một chủ đề khác nhau)


1
Đây có phải là trong bối cảnh hoặc một thủ tục được lưu trữ hoặc T-SQL ad-hoc? Bạn có thể thêm phiên bản SQL Server của bạn làm thẻ không?
George.Palacios

@ George.Palacios Cảm ơn, tôi đã cập nhật câu hỏi. Tôi muốn biết thêm về lý do tại sao điều đó lại quan trọng giữa ad-hoc và sproc.
Jeremy Weir


@Jeremy Chúng tôi không nên quan tâm đến việc thay đổi hay không các giá trị đang thay đổi. Nếu bạn đang sử dụng một biến cục bộ thay vì theo nghĩa đen, bạn sẽ có được ước tính dựa trên sự từ chối * # của các hàng trong bảng thay vì sử dụng biểu đồ để tính toán ước tính số lượng thẻ của bạn.
Zane

Câu trả lời:


11

Được rồi, giả sử rằng bạn đang nói về một biến cục bộ chạy từ truy vấn trong SSMS vì nó không được chỉ định khác. Ngay cả khi bạn sử dụng cùng một giá trị cho giá trị AND UserStatus = @userStatusmà bạn sẽ sử dụng theo nghĩa đen, AND UserStatus = 1bạn sẽ thấy sự khác biệt trong kế hoạch thực hiện của mình do cách ước tính số lượng thẻ được tạo ra.

Khi bạn sử dụng một giá trị bằng chữ, SQL Server sẽ đi ra biểu đồ cho bảng đó và xem giá trị đó phù hợp ở đâu trong khóa phạm vi. Ước tính thu thập được trên đó sẽ dẫn đến một trong hai kịch bản.

HISTOGRAM TRỰC TIẾP HIT Về cơ bản, điều này có nghĩa là có một RANGE_HI_KEYgiá trị (Giá trị cột trên cho bất kỳ bước nào trong biểu đồ) cho giá trị bằng chữ cụ thể đó trong truy vấn của bạn và do đó ước tính sẽ khớp với số EQ_ROWS(# hàng có giá trị bằng RANGE_HI_KEY) trong biểu đồ . Điều này có nghĩa là ước tính của bạn sẽ là số lượng hàng khớp với giá trị đó dựa trên lần cuối bạn cập nhật số liệu thống kê.

LỊCH SỬ INTRA-BƯỚC HIT Đây là khi giá trị tồn tại trong một phạm vi giữa hai RANGE_HI_KEYgiá trị. Khi giá trị bằng chữ của bạn nằm trong phạm vi đó, nó được tính bằng RANGE_ROWS(số lượng hàng giữa hai bước biểu đồ), DINSTINCT_RANGE(số lượng giá trị khác biệt trong bước biểu đồ đó) và AVG_RANGE_ROWS( RANGE_ROWS/ DISTINCT_RANGE_ROWS) và điều đó sẽ cho bạn ước tính của bạn.

Tuy nhiên, khi bạn chạy với một biến cục bộ, bạn sẽ không còn đi đến Biểu đồ cho các giá trị này vì @Variablekhông biết trong thời gian chạy.

Để biết thêm thông tin về chủ đề này, tôi khuyên bạn nên đọc bài báo trắng này của Joe Sack.

DENSITY YAMOR Khi không có giá trị cụ thể nào đi kèm với máy chủ SQL thay vào đó sử dụng Mật độ để có thể xác định số lượng hàng ước tính được trả về cho vị từ đó. Mật độ là 1 / số lượng giá trị riêng biệt trong cột đó. Vì vậy, ước tính cardinality của bạn sẽ là Mật độ * số lượng hàng trong bảng.

Vì vậy, câu chuyện dài không. Ngay cả khi bạn chạy cùng một giá trị lặp đi lặp lại với một biến cục bộ, bạn sẽ không nhận được kết quả tương tự vì những lý do được giải thích thêm trong liên kết Eric Cung cấp từ Kendra Little .


Tôi thêm một sự điều chỉnh nhẹ. Vui lòng quay lại nếu nó không mô tả những gì bạn muốn nói.
John aka hot2use 14/12/18

Trông người đàn ông tốt.
Zane

7

Một giá trị bằng chữ được biết đến với trình tối ưu hóa (vì vậy nó có thể ước tính độ chọn lọc dựa trên giá trị đó).

Một giá trị tham số (thủ tục được lưu trữ, chức năng) được đánh hơi tại thời điểm thực hiện. Một lần thực hiện tiếp theo có thể có một số giá trị khác, mà kế hoạch được biên dịch trước đó có thể không tối ưu.

Đối với một biến, giá trị không được biết đến với trình tối ưu hóa. Nó có thể có thể xem xét mật độ ( trung bình chúng ta có nhiều hàng cho một giá trị nhất định) hoặc nó sử dụng các ước tính có dây cứng (ví dụ như> dẫn đến độ chọn lọc 10% hoặc bất kỳ tỷ lệ phần trăm có dây nào có thể) .


Vì vậy, nếu giá trị sẽ không bao giờ thay đổi, một nghĩa đen có hành động khác với một param không?
Jeremy Weir

1
Vì param sẽ được đánh hơi nên nó sẽ hoạt động giống như nghĩa đen, giả sử bạn luôn có cùng giá trị. Nhưng một biến là một điều hoàn toàn khác!
Tibor Karaszi

Hiểu rồi, vậy có sự khác biệt giữa biến cục bộ được sử dụng làm giá trị tham số và tham số sproc được sử dụng làm giá trị tham số không?
Jeremy Weir

3
@Jeremy Weir: Vâng, đó là lý do tại sao Erik đề nghị đọc bài viết của Brent Ozar ở trên.
Andriy M
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.