SQL Server'ın dizinli görünüm sütunumu NULL-mümkün değil tanımasını nasıl yardımcı olabilirim?


9

SQL Server 2008'de tanımlanmış aşağıdaki dizinli görünüm var ( test amacıyla gist'ten çalışan bir şema indirebilirsiniz ):

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_idve transaction_amountiçindeki tüm NOT NULLsütunlar olarak tanımlanır dbo.transactions. Ancak, Yönetim Studio'nun Nesne Explorer, işaretler hem de görünüm tanımına baktığınızda balance_amountve transaction_countsıra NULLgörünümünde sıfat daha sütunlar.

Bazı tartışmalara göz attım, bunlardan en alakalı olanı, bazı işlevlerin karıştırılmasının SQL Server'ın bir görünüm sütununun her zaman olduğunu tanımasına yardımcı olabileceğini düşündürüyor NOT NULL. Benim durumumda böyle bir karıştırma mümkün değildir, çünkü indeksli görünümlerde toplama işlevleri (örn. ISNULL()Üzerinde SUM()) ifadelerine izin verilmez .

  1. SQL Server fark ben yardım etmenin bir yolu var mı balance_amountve transaction_countvardır NOT NULLsıfat daha?

  2. Değilse, bu sütunların yanlışlıkla NULL-able olarak tanımlanmasından endişe etmem gerekir mi?

    Düşünebileceğim iki endişe:

    • Dengeler görünümüyle eşlenen uygulama nesneleri, dengenin yanlış tanımını alıyor.
    • Çok sınırlı durumlarda, belirli iki optimizasyon Query Optimizer tarafından kullanılamaz, çünkü bu iki sütunun olduğu konusunda bir garantisi yoktur NOT NULL.

    Bu endişelerden herhangi biri önemli midir? Aklımda tutmam gereken başka endişeler var mı?


Evet endişeler var, örneğin ORM'niz nullable tipler oluşturacak, bu da bunları kullanırken kodda ekstra dikkat gerektirecek, bu da sizin durumunuzda işe yaramayacak (hatta yanıltıcı) olacak.
Marcel

Sonunda bir IsNull (..., 0) tedavi edilebilse de, boş bırakılamayan bir alanda (toplama yok) yinelenirken yinelemeli bir sorguda da bir sorun olduğu görülmektedir.
crokusek

Yanıtlar:


10

user_id,, currency_idve transaction_amounttümü NOT NULL,dbo.transactions

Bana öyle geliyor ki SQL Server, nullüzerinde çalıştığı alan (lar) olsa bile bir agreganın üretebileceğine dair kapsamlı bir varsayım var not null. Bu, bazı durumlarda açıkça doğrudur:

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

Ve group bybenzerlerinin genelleştirilmiş versiyonlarında da doğrudurcube

Bu daha basit test durumu, herhangi bir toplamın boş değer olarak yorumlandığı noktayı göstermektedir:

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

IMO bu SQL Server'ın bir sınırlamasıdır (küçük olsa da) - diğer bazı RDBMS'ler, uygulanmayan ve yalnızca optimize ediciye ipuçları vermek için var olan görünümlerde belirli kısıtlamaların oluşturulmasına izin verir, ancak 'benzersizliğin' daha olası olduğunu düşünüyorum 'nullability' den daha iyi bir sorgu planı oluşturulmasında yardım


Sütunun nullabilitesi önemliyse, belki de bir ORM ile kullanım için, dizine alınmış görünümü nullabiliteyi kullanarak yalnızca başka bir görünümde kaydırmayı düşünün 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;

SSMS Nesne Gezgini Ayrıntıları


5

Açıkça olmasalar da, SQL Server'ı bu sütunları boş değerli olarak tanımaya zorlamanın herhangi bir yolu olduğunu sanmıyorum. Örneğin, içindeki ifadeyi nasıl tanımladığınız ISNULL/ COALESCEetrafınızdaki sırasını değiştirmeye çalışabilirsiniz , ancak bu yardımcı olmaz. SUM()

Ayrıca, kaçıracağınız optimizasyonlar olduğuna da inanmıyorum - bu sütunlar şu anda dizine eklenmediğinden, optimize edici, örneğin tüm balance_amountdeğerler> 10000'i belirlemek için farklı bir erişim yöntemi seçebilir . bu sütunlardan birinde kümelenmemiş bir dizin oluşturursanız, dizinin bulunmadığından biraz daha iyi tahminler alabileceğiniz bir durum olabilir, ancak bunun nullability ile ilgisi yoktur.

Performans açısından bu konuda çok endişelenmezdim. Geri döndüm ve yıllar boyunca oluşturduğum bir dizi dizine eklenmiş görünümlere baktım ve bu toplama sütunlarının tümü geçersizdir. Sadece iyi performans gösteriyorlar.

Nesne haritalama ile ilgili olarak, tekrar, bu konuda çok endişelenmezdim. Uygulama dizine alınan görünümü güncelleyemediğinden, bunun balance_amountolabileceğini düşünüp düşünmediği önemli değildir null. Asla bir almaya gidiyor nullve bir yazmayı deneyin olamaz nullbu yüzden, <shrug>.


1
Bilgiçliksel not, [coalesce boşken sütunlara izin verirken isnull olmaz ].
billinkc

@Aaron, nesne haritalama hakkında: Bir haritacı muhtemelen hiçbir zaman bu şekilde kullanılmayacak null olabilecek türlerle işe yaramaz / yanıltıcı nesneler üreteceğinden, bakmaya değer olduğunu düşünüyorum.
Marcel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.