SQL Server가 인덱스 된 뷰 열이 NULL이 아님을 인식하는 데 어떻게 도움이됩니까?


9

SQL Server 2008에 다음과 같은 인덱싱 된 뷰가 정의되어 있습니다 ( 테스트 목적으로 gist에서 작업 스키마 다운로드 할 수 있음 ).

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_amount은 모두의 NOT NULL열로 정의됩니다 dbo.transactions. 그러나, 나는 관리 Studio의 개체 탐색기, 그것은 마크 모두에서 뷰 정의에서 볼 때 balance_amounttransaction_count같은 NULL뷰에서 -able 열.

몇 가지 토론을 살펴 보았습니다. 토론 은 가장 관련이 있습니다. 일부 함수 섞기가 SQL Server 가보기 열이 항상임을 인식하는 데 도움이 될 수 있음을 제안 NOT NULL합니다. 그러나 집계 함수 (예 : ISNULL()이상 SUM())에 대한 표현식 은 인덱싱 된 뷰에서 허용되지 않으므로 그러한 셔플 링은 가능 하지 않습니다 .

  1. SQL 서버가 인식 내가 도울 수있는 방법이 있나요 balance_amount하고 transaction_count있습니다 NOT NULL-able은?

  2. 그렇지 않은 경우 이러한 열이 실수로 NULL-able 로 식별되는 것에 대해 우려해야 합니까?

    내가 생각할 수있는 두 가지 문제는 다음과 같습니다.

    • 저울보기에 매핑 된 응용 프로그램 객체가 저울의 잘못된 정의를 받고 있습니다.
    • 매우 제한된 경우에,이 두 열이이라는 것을 보증하지 않기 때문에 Query Optimizer가 특정 최적화를 사용할 수 없습니다 NOT NULL.

    이러한 우려 중 하나가 큰 문제입니까? 명심해야 할 다른 문제가 있습니까?


예를 들어, ORM이 널 입력 가능 유형을 작성하여 사용시 코드를 추가로 관리해야하는 경우가 있습니다. 이는 사용자의 경우 쓸모 없거나 오해의 소지가 있습니다.
Marcel

또한 마지막에 IsNull (..., 0)이 치료 될 수 있지만 Null을 허용하지 않는 필드 (집계 없음)에서 재귀를 수행 할 때 재귀 적 cte에서 문제가되는 것으로 보입니다.
crokusek 2013

답변:


10

user_id, currency_idtransaction_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는 적용되지 않고 뷰에 대한 특정 제약 조건을 생성하여 옵티 마이저에게 단서를 줄 수는 있지만 '고유성'이 더 가능성이 있다고 생각합니다. '널링 가능성'보다 좋은 쿼리 계획을 생성하는 데 도움


열의 Null 허용 여부가 ORM과 함께 사용하기에 중요한 경우 인덱싱 된 뷰를 ISNULL다음을 사용하여 Null 허용 여부를 보장하는 다른 뷰로 래핑하는 것이 좋습니다 .

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 개체 탐색기 세부 정보


5

SQL Server가 이러한 열을 명확하게 알 수는 없지만 null을 허용하지 않는 것으로 인식하도록 할 수있는 방법은 없다고 생각합니다. 예를 들어, 내부 에서 표현식 을 정의 ISNULL/ COALESCE주위하는 방법의 순서를 변경하려고 시도 할 수 있지만 도움이되지는 않습니다. SUM()

또한 누락 할 최적화가 있다고 생각하지 않습니다.이 열은 현재 색인화되어 있지 않으므로 최적화 프로그램이 모든 액세스 balance_amount값> 10000 을 결정하기 위해 다른 액세스 방법을 선택할 수있는 것은 아닙니다. 이러한 열 중 하나에 비 클러스터형 인덱스를 만드는 경우 인덱스가없는 경우보다 약간 더 나은 추정치를 얻을 수 있지만 이는 Null 허용과 관련이없는 상황 일 수 있습니다.

나는 성능 관점에서 이것에 대해 너무 걱정하지 않을 것입니다. 나는 몇 년 동안 내가 만든 여러 인덱스 된 뷰를 보았고 이러한 집계 열은 모두 null이 가능합니다. 그들은 잘 수행합니다.

객체 매핑에 관한 한, 나는 그것에 대해 너무 걱정하지 않을 것입니다. 응용 프로그램이 인덱싱 된 뷰를 업데이트 할 수 없기 때문에이 그 생각하면, 그것은 중요하지 않습니다 balance_amount수 있습니다 null. 결코를받을 않을 것 null, 그리고 그것은을 작성하려고 할 수 null있도록, <shrug>.



@Aaron, 객체 매핑에 대해 : 매퍼가 실제로 사용되지 않는 nullable 유형으로 쓸모없고 오해의 소지가있는 객체를 생성 할 가능성이 있기 때문에 살펴볼 가치가 있다고 생각합니다.
Marcel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.