2012-11-26 5 views
1

이 특정 쿼리와 관련하여 :왜 불평등은 결과를 동등보다 빨리 반환합니까?

쿼리 된 데이터를 이해할 필요가 없습니다. 이는 부적절합니다.

SELECT 
    de.DocumentEntryId, 
    de.Number, 
    currentdev.ToIgnore, 
    previousdev.ToIgnore, 
    currentdev.DocumentEntryValueId AS CurrentDocumentEntryValueId, 
    SUM(currentper.Value) AS CurrentPaymentRate, 
    SUM(currentdevr.ConversionRate) AS CurrentConversionRate, 
    MAX(previousdev.DocumentEntryValueId) AS PreviousDocumentEntryValueId, 
    SUM(previousper.Value) AS PreviousPaymentRate, 
    SUM(previousdevr.ConversionRate) AS PreviousConversionRate 
FROM 
    DocumentEntry de 
    INNER JOIN PaymentEntry currentpe ON currentpe.PaymentEntryId = de.CurrentPaymentEntryId 
    INNER JOIN DocumentEntryValue currentdev ON currentpe.DocumentEntryValueId = currentdev.DocumentEntryValueId 
    INNER JOIN DocumentEntryValue previousdev ON previousdev.DocumentEntryId = de.DocumentEntryId 
    INNER JOIN PaymentEntryRate currentper ON currentpe.PaymentEntryId = currentper.PaymentEntryId 
    INNER JOIN DocumentEntryValueRate currentdevr ON currentdev.DocumentEntryValueId = currentdevr.DocumentEntryValueId 
    INNER JOIN PaymentEntry previouspe ON previousdev.DocumentEntryValueId = previouspe.DocumentEntryValueId 
    INNER JOIN PaymentEntryRate previousper ON previouspe.PaymentEntryId = previousper.PaymentEntryId 
    INNER JOIN DocumentEntryValueRate previousdevr ON previousdevr.DocumentEntryValueId = previousdev.DocumentEntryValueId 
WHERE 
    previousdev.DocumentEntryValueId <> currentdev.DocumentEntryValueId 
    AND currentdev.ToIgnore <> 1 
    AND previousdev.ToIgnore <> 1 
    AND currentpe.PaymentId = previouspe.PaymentId 
GROUP BY 
    de.DocumentEntryId, 
    de.Number, 
    currentdev.ToIgnore, 
    previousdev.ToIgnore, 
    currentdev.DocumentEntryValueId 
ORDER BY DocumentEntryId 

특히이 두 불평등 :

AND currentdev.ToIgnore <> 1 
AND previousdev.ToIgnore <> 1 

: ToIgnore는 비트 열이다

그냥 절가 를보십시오.

이 쿼리는 약 1300 개의 행을 반환하는 데 약 10 초가 걸립니다. 나는 평등 연산자를 사용하려면 다음 두 줄을 변경하는 경우

그러나 :

AND currentdev.ToIgnore = 0 
AND previousdev.ToIgnore = 0 

그것은 아무것도 반환 영원히합니다.

DocumentEntry 인덱스 :

ALTER TABLE [dbo].[DocumentEntry] ADD CONSTRAINT [DocumentEntry$0] PRIMARY KEY CLUSTERED 
(
    [DocumentEntryId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [IDX_DOCUMENTENTRY_REFNUMBER] ON [dbo].[DocumentEntry] 
(
    [EntryReferenceNumber] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [missing_index_14227] ON [dbo].[DocumentEntry] 
(
    [MasterDocumentEntryId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [missing_index_186297_186296_DocumentEntry] ON [dbo].[DocumentEntry] 
(
    [Number] ASC 
) 
INCLUDE ( [DocumentEntryId]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

DocumentEntryValue 인덱스 :

ALTER TABLE [dbo].[DocumentEntryValue] ADD CONSTRAINT [DocumentEntryValue$0] PRIMARY KEY CLUSTERED 
(
    [DocumentEntryValueId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [IDX_DOCUMENTENTRYVALUE_DOCENTRYID] ON [dbo].[DocumentEntryValue] 
(
    [DocumentEntryId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 


CREATE NONCLUSTERED INDEX [IDX_DOCUMENTENTRYVALUE_REFNUMBER] ON [dbo].[DocumentEntryValue] 
(
    [EntryValueReferenceNumber] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 


CREATE NONCLUSTERED INDEX [missing_index_4022_4021_DocumentEntryValue] ON [dbo].[DocumentEntryValue] 
(
    [ReferenceDocumentId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

DocumentEntryValueRate 그것은이 도움이

, 여기에 각 테이블에서 인덱스입니다 ...에서 dexes :

ALTER TABLE [dbo].[DocumentEntryValueRate] ADD CONSTRAINT [DocumentEntryValueRate$0] PRIMARY KEY CLUSTERED 
(
    [DocumentEntryValueRateId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 


CREATE NONCLUSTERED INDEX [missing_index_56865_56864_DocumentEntryValueRate] ON [dbo].[DocumentEntryValueRate] 
(
    [DocumentEntryValueId] ASC 
) 
INCLUDE ( [timestamp], 
    [DocumentEntryValueRateId], 
    [RateId], 
    [RateVersionId], 
    [RateTypeId], 
    [RateGroupId], 
    [RatePeriodValueId], 
    [ConversionRate]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

PaymentEntry 인덱스 :

ALTER TABLE [dbo].[PaymentEntry] ADD CONSTRAINT [PaymentEntry$0] PRIMARY KEY CLUSTERED 
(
    [PaymentEntryId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [IDX_PAYMENTENTRY_DOCENTRYVALUEID] ON [dbo].[PaymentEntry] 
(
    [DocumentEntryValueId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [missing_index_2517_2516_PaymentEntry] ON [dbo].[PaymentEntry] 
(
    [PaymentId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

PaymentEntryRate 인덱스 : 나는 평등 연산자를 사용할 때 여기

ALTER TABLE [dbo].[PaymentEntryRate] ADD CONSTRAINT [PaymentEntryRate$0] PRIMARY KEY CLUSTERED 
(
    [PaymentEntryRateId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [IDX_PAYMENTENTRYRATE_PAYMENTENTRYID] ON [dbo].[PaymentEntryRate] 
(
    [PaymentEntryId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [missing_index_2618_2617_PaymentEntryRate] ON [dbo].[PaymentEntryRate] 
(
    [RateId] ASC 
) 
INCLUDE ( [timestamp], 
    [PaymentEntryRateId], 
    [PaymentEntryId], 
    [RateTypeId], 
    [RateGroupId], 
    [RateVersionId], 
    [RatePeriodValueId], 
    [Value]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

CREATE NONCLUSTERED INDEX [missing_index_2686_2685_PaymentEntryRate] ON [dbo].[PaymentEntryRate] 
(
    [RateTypeId] ASC, 
    [RateId] ASC, 
    [RatePeriodValueId] ASC 
) 
INCLUDE ( [PaymentEntryId]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data Filegroup 1] 

이 예상 실행 계획의 일부입니다 (= 0) : Estimated execution plan

누군가이 경우 (또는 대부분의 경우) 부등호 연산자가 평등 연산자보다 빠르게 보이는 이유를 설명 할 수 있습니까?

+1

단서의 두 쿼리에 대한 실제 실행 계획을 비교 했습니까? –

+0

불평등 쿼리에서 실행 계획을 얻을 수 있지만 평등 쿼리는 그냥 영원히 실행됩니다 ... –

+2

비트 필드는 두 개가 아니라 세 가지 상태를 기억하십시오. –

답변

1

이유는 확실하지 않지만 의견 만 게시 할 수는 없으므로 답변 만 가능하므로이 기능이 작동하지 않는다면 무시하십시오.

"WHERE ToIgnore = 0"으로 비 클러스터형 인덱스를 생성하면 문제를 해결해야합니다.

ToIgnore = 1이고 ToIgnore = 0 인 레코드의 레코드 수는 얼마입니까? 내 생각 엔 ToIngore = 1 인 레코드의 양은 0으로 설정된 것보다 훨씬 큽니다.

나는 오라클/SQL DBA가 마이크로 소프트가 문제를 설명 할 것이기 때문에 비트 열에 인덱스가 필요 없다는 것을 잠시 기억하고있다. 그러나 백업 할 항목을 찾을 수 없으며 오라클과 뭔가 다를 수 있습니다. MS는 MS도이를 수행해야한다고 생각했습니다.

+0

그것은 반대입니다 : SELECT COUNT (*) From DocumentEntryValue WhereIgnore = 0은 288123 개의 행을 반환합니다. SELECT COUNT (*) From DocumentEntryValue WHERE ToIgnore = 1은 217 개의 행을 반환합니다. –

+1

동일한 scenerio를 실행하려고하는데 12 분 288000 개의 레코드를 테이블에 삽입하려고합니다. :/ – Switch

+1

오케이, 나는 ToIgnore 필드로 1을 가진 288000 레코드를 추가하여 테이블을 만들었습니다. ToIgnore 필드에 0을 추가로 240 개의 레코드를 추가했습니다. 이 테이블에는 인덱스가 없습니다. 아무리 실행해도 타이밍은 항상 동일합니다. 실행 계획을 보았을 때 언제나 100 % 테이블 스캔을 수행합니다. <>와 = 사이에 어떤 종류의 작업 차이가 있는지 찾기 위해 연산자 우선 순위 (Operator Precedence)를 찾아 보았습니다. http://msdn.microsoft.com/en-us/library/ms190276.aspx 내 생각 엔 인덱스 문제 일 수 있으며 MS는 귀하의 작은 변경 사항에 따라 다른 쿼리를 평가합니다. – Switch

관련 문제