Tại sao SQL Tối ưu hóa không sử dụng ràng buộc của tôi?


7

Tôi muốn tạo một bảng với một NOT NULLcột bool.
Tôi sử dụng TINYINTvới sự CHECKràng buộc BETWEEN 0 and 1. Các ràng buộc là mới và do đó đáng tin cậy

Bây giờ tôi mong rằng trình tối ưu hóa SQL bây giờ biết rằng cột này chỉ có thể là 0 và 1 vì vậy khi tôi viết truy vấn, col >= 2tôi sẽ thấy Constant Scan trong kế hoạch thực hiện thực tế (như khi tôi sẽ kiểm tra NULLhoặcSELECT TOP (0)

Nhưng đây không phải là trường hợp, nó phù hợp với Quét bảng. Tôi cũng cần phải có chỉ mục trên cột này?

Trong thử nghiệm của tôi dưới đây tôi sử dụng TINYINTvới CHECKràng buộc. Loại người dùng xác định dựa trên TINYINTràng buộc RULEvà cũ tốt BIT.

GO
CREATE TYPE dbo.myBool 
FROM [INT] NOT NULL
GO

CREATE RULE dbo.R_Bool AS @value BETWEEN 0 AND 1
go

EXEC sys.sp_bindrule @rulename = N'R_Bool'
                   , @objname = N'myBool'
GO 


DROP TABLE IF EXISTS dbo.RuleTest
CREATE TABLE dbo.RuleTest
(
    Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , oldSchoolBool TINYINT NOT NULL CHECK (oldSchoolBool BETWEEN 0 AND 1)
    , customBool dbo.myBool NOT NULL
    , myBit BIT NOT NULL
)

;WITH tally (n)
AS
(
    SELECT 
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    FROM        (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0))   AS a(n)
    CROSS JOIN  (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0))   AS b(n)
    CROSS JOIN  (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0))   AS c(n)

)
INSERT INTO dbo.RuleTest 
(oldSchoolBool, customBool, myBit)
SELECT
    ABS(CHECKSUM(NewId())) % 2 
    ,ABS(CHECKSUM(NewId())) % 2 
    ,ABS(CHECKSUM(NewId())) % 2 
FROM tally t

SET STATISTICS IO ON;

SELECT * FROM dbo.RuleTest rt
WHERE rt.oldSchoolBool IS NULL


SELECT * FROM dbo.RuleTest rt
WHERE rt.oldSchoolBool >=2 

go
SELECT * FROM dbo.RuleTest rt
WHERE rt.customBool >=2 
go
SELECT * FROM dbo.RuleTest rt
WHERE rt.myBit >= 2

SET STATISTICS IO OFF;

Tôi thấy một Quét liên tục cho kiểm tra NULL và 3 lần quét bảng cho phần còn lại.


Nếu bạn muốn sử dụng như một kiểu boolean thì tại sao tinyint trong máy chủ sql, bạn có thể sử dụng kiểu dữ liệu BIT.
Learning_DBAdmin

Đây là lý thuyết, cũng có thể có lý do cho việc không sử dụng một chút, như tính toán hoặc tổng hợp.
Zikato

1
Tôi tự hỏi tại sao bạn có WHERE myBit >= 2điều kiện khi bạn biết các giá trị không bao giờ có thể lớn hơn 1.
ypercubeᵀᴹ

Câu trả lời:


11

Truy vấn 2

Vấn đề là tự động tham số hóa .

Trong trường hợp của bạn, hằng số 2được thay thế bằng tham số tinyint @1chứ không phải bằng chữ 2- vì tham số này có thể có giá trị 0hoặc 1nó sẽ không hợp lệ để trình tối ưu hóa truy vấn giả định ràng buộc kiểm tra mâu thuẫn với điều này.

Bạn có thể sử dụng truy vấn sau đây để có kế hoạch sử dụng phát hiện mâu thuẫn ( 1=1ngăn chặn tham số tự động) Phát hiện mâu thuẫn sau đó xảy ra như một phần của đơn giản hóa (xem sơ đồ Đường ống tối ưu hóa ở đây).

SELECT * 
FROM dbo.RuleTest rt
WHERE rt.oldSchoolBool >=2 and 1=1

kế hoạch kết quả được đơn giản hóa để quét liên tục

nhập mô tả hình ảnh ở đây

Truy vấn 3

Các quy tắc đã không được khuyến khích / không được chấp nhận trong khoảng 20 năm. 2000 BOL mô tả chúng như là

một tính năng tương thích ngược ... ràng buộc KIỂM TRA là cách tiêu chuẩn, ưa thích

Các CREATE RULEbang chủ đề

Các quy tắc không áp dụng cho dữ liệu đã có trong cơ sở dữ liệu tại thời điểm quy tắc được tạo

Vì vậy, tôi tưởng tượng những điều này không bao giờ được tin tưởng bởi trình tối ưu hóa truy vấn vì có thể thực hiện các thao tác sau và có dữ liệu không tuân thủ quy tắc

CREATE TYPE dbo.myBool FROM [INT] NOT NULL

GO

CREATE TABLE dbo.RuleTest
(
  customBool dbo.myBool NOT NULL
)

INSERT INTO  dbo.RuleTest VALUES (10)

go

CREATE RULE dbo.R_Bool AS @value BETWEEN 0 AND 1
GO

EXEC sys.sp_bindrule @rulename = N'R_Bool'
                   , @objname = N'myBool'

Về mặt kỹ thuật, có thể duy trì một khái niệm quy tắc đáng tin cậy tương tự như các ràng buộc đáng tin cậy, tôi không tin điều này tồn tại.

Truy vấn 4

Bạn cần thêm một ràng buộc kiểm tra dự phòng CHECK (myBit BETWEEN 0 AND 1)hoặc tương đương nếu bạn muốn nó thực hiện phát hiện mâu thuẫn này. Mặc dù một bit không nullable chỉ có thể giữ hai giá trị mà bạn không phát hiện ra mâu thuẫn này mà không có


Tôi đã kiểm tra nó và nó trả về quét liên tục cho oldSchoolBool, nhưng không phải hai cái còn lại (loại tùy chỉnh và bit), lý do nào? Nó phù hợp với cả điều kiện của bạn) 1 = 1 và Brent's (1 = (CHỌN 1))
Zikato

@MarinSmith Quy tắc là nội dung của những huyền thoại, nhưng rất thực tế trên một số máy chủ sản xuất. Còn Bit?
Zikato
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.