ฉันจะช่วย SQL Server ให้รู้ได้อย่างไรว่าคอลัมน์มุมมองที่จัดทำดัชนีของฉันไม่เป็น NULL


9

ฉันมีมุมมองการจัดทำดัชนีต่อไปนี้กำหนดไว้ใน SQL Server 2008 (คุณสามารถดาวน์โหลด schema การทำงานจากส่วนสำคัญสำหรับการทดสอบ):

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_idและtransaction_amountมีการกำหนดไว้ทั้งหมดเป็นคอลัมน์ในNOT NULL dbo.transactionsอย่างไรก็ตามเมื่อฉันดูคำจำกัดความของมุมมองใน Object Explorer ของ Management Studio มันจะทำเครื่องหมายคอลัมน์ทั้งสองbalance_amountและtransaction_countเป็นNULL-able ในมุมมอง

ฉันเอาดูที่การอภิปรายหลาย, คนนี้เป็นที่เกี่ยวข้องมากที่สุดของพวกเขาที่แนะนำสับของฟังก์ชั่นบางอย่างอาจช่วย SQL Server NOT NULLยอมรับว่าคอลัมน์มุมมองอยู่เสมอ ในกรณีของฉันไม่สามารถสับแบบนี้ได้เนื่องจากไม่อนุญาตให้มีการแสดงออกในฟังก์ชั่นรวม (เช่นISNULL()over the SUM()) ในมุมมองที่จัดทำดัชนี

  1. มีวิธีที่ฉันสามารถช่วย SQL Server ตระหนักดีว่าbalance_amountและtransaction_countมีความNOT NULLน่า?

  2. หากไม่มีฉันควรมีข้อกังวลใด ๆ เกี่ยวกับคอลัมน์เหล่านี้ที่ถูกระบุว่าผิดNULL- ใช้ได้หรือไม่

    สองข้อกังวลที่ฉันคิดได้คือ:

    • แอปพลิเคชันวัตถุใด ๆ ที่แมปกับมุมมองยอดดุลจะได้รับการกำหนดที่ไม่ถูกต้องของยอดดุล
    • ในกรณีที่มีข้อ จำกัด อย่างมากการปรับให้เหมาะสมบางอย่างจะไม่สามารถใช้ได้กับ Query Optimizer เนื่องจากไม่มีการรับประกันจากมุมมองที่เป็นสองคอลัมน์NOT NULLนี้

    สิ่งเหล่านี้เกี่ยวข้องกับเรื่องใหญ่หรือไม่? มีข้อกังวลอื่น ๆ ที่ฉันควรทราบหรือไม่


ใช่มีข้อกังวลเช่น ORM ของคุณจะสร้างประเภท nullable ซึ่งจะต้องระมัดระวังเป็นพิเศษในการใช้รหัสเมื่อใช้พวกเขาซึ่งไม่มีประโยชน์ (หรือแม้แต่ทำให้เข้าใจผิด) ในกรณีของคุณ
Marcel

สิ่งนี้ดูเหมือนว่าจะเป็นปัญหาใน curs แบบเรียกซ้ำเมื่อเรียกใช้ซ้ำบนฟิลด์ที่ไม่เป็นโมฆะ (ไม่มีการรวม) แม้ว่า IsNull (... , 0) ในตอนท้ายจะสามารถแก้ไขได้
crokusek

คำตอบ:


10

user_id, currency_idและtransaction_amountถูกกำหนดให้เป็นNOT NULLคอลัมน์ในdbo.transactions

ฉันคิดว่า SQL Server มีสมมติฐานครอบคลุมว่าการรวมสามารถสร้างnullแม้ว่าเขตข้อมูลที่ทำงานอยู่not nullนั้น นี่เป็นความจริงที่เห็นได้ชัดในบางกรณี:

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

และยังเป็นจริงในรุ่นทั่วไปของgroup byชอบcube

กรณีทดสอบที่ง่ายกว่านี้แสดงให้เห็นถึงจุดที่ผลรวมใด ๆ ถูกตีความว่าเป็นโมฆะ:

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

IMO นี่เป็นข้อ จำกัด (แม้ว่าจะเป็นรอง) ของ SQL Server - RDBMS อื่น ๆ บางตัวอนุญาตให้สร้างข้อ จำกัด บางอย่างในมุมมองที่ไม่ได้บังคับใช้และมีอยู่เพียงเพื่อให้เบาะแสกับเครื่องมือเพิ่มประสิทธิภาพ แต่ฉันคิดว่า 'เอกลักษณ์' มีแนวโน้มมากกว่า ช่วยในการสร้างแผนแบบสอบถามที่ดีกว่า 'nullability'


หากความไม่แน่นอนของคอลัมน์มีความสำคัญอาจจะใช้กับ ORM ให้พิจารณาการตัดมุมมองที่จัดทำดัชนีไว้ในมุมมองอื่นที่รับประกันความสามารถในการทำให้เป็นโมฆะไม่ได้โดยใช้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;

รายละเอียด Explorer วัตถุ SSMS


5

ฉันไม่คิดว่าจะมีวิธีใดที่คุณสามารถบังคับให้ SQL Server จดจำคอลัมน์เหล่านี้ว่าไม่เป็นโมฆะแม้ว่าจะไม่ชัดเจนก็ตาม คุณสามารถลองเปลี่ยนลำดับวิธีที่คุณกำหนดISNULL/ COALESCEรอบนิพจน์ภายใน SUM()ตัวอย่างเช่น แต่มันจะไม่ช่วย

ฉันยังไม่เชื่อว่ามีการเพิ่มประสิทธิภาพใด ๆ ที่คุณจะพลาด - คอลัมน์เหล่านี้ยังไม่ได้จัดทำดัชนีดังนั้นจึงไม่เหมือนกับเครื่องมือเพิ่มประสิทธิภาพที่สามารถเลือกวิธีการเข้าถึงที่แตกต่างกันเพื่อพิจารณาพูดbalance_amountค่าทั้งหมด> 10,000 ที่นั่น อาจเป็นสถานการณ์ที่หากคุณสร้างดัชนีที่ไม่ทำคลัสเตอร์ในหนึ่งในคอลัมน์เหล่านั้นคุณอาจได้รับการประมาณการที่ดีขึ้นเล็กน้อยกว่าหากไม่มีดัชนีอยู่ แต่สิ่งนี้ไม่เกี่ยวข้องกับความไม่สามารถทำได้

ฉันจะไม่กังวลเกี่ยวกับสิ่งนี้จากมุมมองการแสดง ฉันกลับไปดูที่มุมมองที่มีการจัดทำดัชนีหลายรายการที่ฉันสร้างขึ้นในช่วงหลายปีที่ผ่านมาและคอลัมน์สรุปรวมเหล่านี้ทั้งหมดเป็นโมฆะ พวกเขาทำงานได้ดี

เท่าที่การทำแผนที่วัตถุเกิดขึ้นอีกครั้งฉันก็ไม่ต้องกังวลกับมันมากนัก เนื่องจากแอปพลิเคชันไม่สามารถอัปเดตมุมมองที่จัดทำดัชนีได้จึงไม่สำคัญว่าbalance_amountจะเป็นnullไปได้หรือไม่ มันไม่เคยจะได้รับnullและไม่สามารถพยายามที่จะเขียนเพื่อnull<shrug>



@Aaron เกี่ยวกับการทำแผนที่วัตถุ: ฉันคิดว่ามันคุ้มค่าที่จะดูเนื่องจาก mapper อาจสร้างวัตถุที่ไร้ประโยชน์ / ทำให้เข้าใจผิดด้วยประเภท nullable ที่จะไม่ใช้จริง ๆ เช่นนี้
Marcel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.