Làm cách nào tôi có thể giúp SQL Server nhận ra cột xem được lập chỉ mục của tôi là KHÔNG thể NULL?


9

Tôi có chế độ xem được lập chỉ mục sau được xác định trong SQL Server 2008 (bạn có thể tải xuống một lược đồ làm việc từ ý chính cho mục đích thử nghiệm):

CREATE VIEW dbo.balances
WITH SCHEMABINDING
AS
SELECT
      user_id
    , currency_id

    , SUM(transaction_amount)   AS balance_amount
    , COUNT_BIG(*)              AS transaction_count
FROM dbo.transactions
GROUP BY
      user_id
    , currency_id
;
GO

CREATE UNIQUE CLUSTERED INDEX UQ_balances_user_id_currency_id
ON dbo.balances (
      user_id
    , currency_id
);
GO

user_id, currency_idtransaction_amounttất cả được định nghĩa là NOT NULLcác cột trong dbo.transactions. Tuy nhiên, khi tôi nhìn vào định nghĩa khung nhìn trong Object Management Studio Explorer, nhãn hiệu cả nó balance_amounttransaction_countnhư NULLcột -able trong giao diện.

Tôi đã xem qua một số cuộc thảo luận, cuộc thảo luận này có liên quan nhất trong số đó, cho thấy một số chức năng xáo trộn có thể giúp SQL Server nhận ra rằng một cột xem luôn luôn NOT NULL. Tuy nhiên, không có sự xáo trộn nào như vậy trong trường hợp của tôi, vì các biểu thức trên các hàm tổng hợp (ví dụ: ISNULL()trên SUM()) không được phép trong các khung nhìn được lập chỉ mục.

  1. Có cách nào tôi có thể giúp SQL Server nhận ra điều đó balance_amounttransaction_countcó thể thực hiện được NOT NULLkhông?

  2. Nếu không, tôi có nên lo lắng về việc các cột này bị xác định nhầm là NULLkhông thể?

    Hai mối quan tâm tôi có thể nghĩ đến là:

    • Bất kỳ đối tượng ứng dụng nào được ánh xạ tới chế độ xem số dư đều nhận được định nghĩa không chính xác về số dư.
    • Trong các trường hợp rất hạn chế, một số tối ưu hóa nhất định không có sẵn cho Trình tối ưu hóa truy vấn vì nó không có sự đảm bảo từ quan điểm rằng hai cột này NOT NULL.

    Là một trong những mối quan tâm này là một vấn đề lớn? Có bất kỳ mối quan tâm nào khác tôi nên ghi nhớ?


Có những lo ngại, ví dụ ORM của bạn sẽ tạo ra các loại không thể, do đó sẽ cần thêm sự cẩn thận trong mã khi sử dụng chúng, điều này là vô ích (hoặc thậm chí sai lệch) trong trường hợp của bạn.
Marcel

Điều này cũng có vẻ là một vấn đề trong một cte đệ quy khi đệ quy trên một trường không null (không tổng hợp) mặc dù cuối cùng IsNull (..., 0) có thể chữa được.
crokusek

Câu trả lời:


10

user_id, currency_idtransaction_amounttất cả được định nghĩa là NOT NULLcác cột trongdbo.transactions

Theo tôi, SQL Server có một giả định cụ thể rằng một tập hợp có thể tạo ra nullngay cả khi (các) trường mà nó hoạt động not null. Điều này rõ ràng là đúng trong một số trường hợp:

create table foo(bar integer not null);
select sum(bar) from foo
-- returns 1 row with `null` field

Và cũng đúng trong các phiên bản tổng quát của group bylikecube

Trường hợp kiểm tra đơn giản hơn này minh họa điểm mà bất kỳ tổng hợp nào được hiểu là không thể:

CREATE VIEW dbo.balances
with schemabinding
AS
SELECT
      user_id
    , sum(1)   AS balance_amount
FROM dbo.transactions
GROUP BY
      user_id
;
GO

IMO đây là một hạn chế (dù chỉ là một lỗi nhỏ) của SQL Server - một số RDBMS khác cho phép tạo ra các ràng buộc nhất định đối với các chế độ xem không được thi hành và chỉ tồn tại để đưa ra manh mối cho trình tối ưu hóa, mặc dù tôi nghĩ rằng 'tính duy nhất' có nhiều khả năng giúp tạo ra một kế hoạch truy vấn tốt hơn 'nullable'


Nếu tính không có giá trị của cột là quan trọng, có lẽ để sử dụng với ORM, hãy xem xét việc bọc chế độ xem được lập chỉ mục trong chế độ xem khác chỉ đơn giản là đảm bảo tính không có giá trị bằng cách sử dụng ISNULL:

CREATE VIEW dbo.balancesORM
WITH SCHEMABINDING
AS
SELECT 
    B.[user_id],
    B.currency_id,
    balance_amount = ISNULL(B.balance_amount, 0),
    transaction_count = ISNULL(B.transaction_count, 0)
FROM dbo.balances AS B;

Chi tiết thám hiểm đối tượng SSMS


5

Tôi không nghĩ có bất kỳ cách nào bạn có thể buộc SQL Server nhận ra các cột này là không thể rỗng, mặc dù chúng rõ ràng là không. Ví dụ, bạn có thể cố gắng thay đổi thứ tự cách bạn xác định ISNULL/ COALESCExung quanh biểu thức bên trong SUM() , nhưng điều đó sẽ không có ích.

Tôi cũng không tin có bất kỳ tối ưu hóa nào bạn sẽ bỏ lỡ - những cột đó hiện chưa được lập chỉ mục, vì vậy không giống như trình tối ưu hóa có thể chọn một phương thức truy cập khác để xác định, giả sử, tất cả các balance_amountgiá trị> 10000. Ở đó có thể là một tình huống nếu bạn tạo một chỉ mục không được nhóm trên một trong những cột đó, bạn có thể có được ước tính tốt hơn một chút so với nếu chỉ mục không có ở đó, nhưng điều này không liên quan gì đến tính vô hiệu.

Tôi sẽ không quá lo lắng về điều này từ góc độ hiệu suất. Tôi đã quay lại và xem xét một loạt các khung nhìn được lập chỉ mục mà tôi đã tạo trong nhiều năm qua và các cột tổng hợp này đều không có giá trị. Họ thực hiện tốt.

Theo như ánh xạ đối tượng, một lần nữa, tôi sẽ không quá lo lắng về nó. Vì ứng dụng không thể cập nhật chế độ xem được lập chỉ mục, nên nó không thành vấn đề nếu nó nghĩ là balance_amountcó thể null. Nó sẽ không bao giờ nhận được một null, và nó không thể cố gắng viết một null, vì vậy <shrug>.



@Aaron, về ánh xạ đối tượng: Tôi cho rằng nó đáng để xem xét, vì một người lập bản đồ có thể sẽ tạo ra các đối tượng vô dụng / gây hiểu lầm với các loại nullable sẽ không bao giờ được sử dụng như vậy.
Marcel
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.