2015-07-27 8 views
1

У меня есть следующая таблица с 1 миллиардом записей.SQL Server 2008 R2: запрос настройки

create table PfTest 
(
    cola int, 
    colb int, 
    colc date, 
    cold varchar(10), 
    ID int 
); 

Теперь я хочу отображать записи, относящиеся к конкретным датам, а не в определенные даты.

Для которого я использую следующие 2-х типов запросов:

Запрос 1:

select DISTINCT cola, colb, colc, cold, ID 
from PfTest 
WHERE colc In ('2014-01-01') 
    AND cold NOT IN (SELECT cold 
        FROM PfTest 
        WHERE ID = 1 
        AND colc IN ('2014-01-02', '2014-01-03', 
            '2014-01-04', '2014-01-05', '2014-01-06')); 

Query 2:

WITH cte AS 
(
    SELECT DISTINCT cola, colb, colc, cold, ID 
    FROM PfTest 
    WHERE cold NOT IN (SELECT cold FROM PfTest 
         WHERE ID = 1 
         AND colc IN('2014-01-02', '2014-01-03', 
            '2014-01-04', '2014-01-05', '2014-01-06')) 
) 
SELECT cola, colb, colc, cold, ID 
FROM cte 
WHERE colc IN ('2014-01-01'); 

Над обоими планами запросов одинаковы для исполнения. И оба требуют огромного времени для исполнения. Могу ли я написать несколько лучших запросов для этой ситуации?

+0

У вас есть «ПК» на вашем столе, а также любой индекс? –

+0

@FelixPamittan, Yup! У меня есть 'PK', а не кластеризованный индекс. – MAK

+1

Это 'ID' правильно? Затем вы можете удалить 'DISTINCT'. –

ответ

2

Это ваш запрос, без DISTINCT (что кажется ненужным):

select cola, colb, colc, cold, ID 
from PfTest 
WHERE colc In ('2014-01-01') AND 
     cold NOT IN (SELECT cold 
        from PfTest 
        WHERE ID = 1 AND 
         colc IN ('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06') 
       ); 

Я хотел бы начать с индексами. PFTest(colc, cold) и PFTest(id, colc, cold).

Если подзапрос возвращает много данных - например, миллионы строк - тогда это может быть случай, когда вам лучше провести временную таблицу. Сначала я попробую индекс. Если это не сработает, временная таблица с индексом на cold может работать. Кроме того, несмотря на то, что будет иметь незначительное влияние на производительность, я бы фраза запрос с использованием NOT EXISTS, а не NOT IN:

select cola, colb, colc, cold, ID 
from PfTest t 
WHERE colc In ('2014-01-01') AND 
     NOT EXISTS (SELECT 1 
        from PfTest t2 
        WHERE t2.cold = t1.cold AND t2.ID = 1 AND 
         t2.colc IN ('2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06') 
       ); 

Для этой версии, лучший показатель PfTest(cold, id, colc).

NOT EXISTS имеет более интуитивное поведение, когда соответствующие столбцы имеют значения NULL.

+1

Если 'ID' является' PK', а также ключ кластеризации, необходим ли второй индекс? –

+0

@ Gordon Linoff, на каком столбце вы создали первичный ключ и кластерный индекс? А на каких столбцах некластеризованный индекс? Вы использовали комбинированные индексы? – MAK

+0

@ Гордон Линофф, да! Ты прав. Огромное спасибо. – MAK

1

Во-первых

select DISTINCT cola, colb, colc, cold, ID 
from PfTest 
WHERE colc In ('2014-01-01') 
    AND cold NOT IN (SELECT cold 
        FROM PfTest 
        WHERE ID = 1 
        AND colc IN ('2014-01-02', '2014-01-03', 
            '2014-01-04', '2014-01-05', '2014-01-06')); 

такое же как

select DISTINCT cola, colb, colc, cold, ID 
from PfTest 
WHERE colc In ('2014-01-01') 
    AND colc NOT IN ('2014-01-02', '2014-01-03', 
            '2014-01-04', '2014-01-05', '2014-01-06') 

И НЕ (ID = 1);

потому что внутренние и внешние таблицы одинаковы.

Поскольку вы не хотите повторно использовать таблицы снова и снова (потому что он содержит миллиард строк), использование данных, привязанных к таблице темпа, является лучшей практикой. А затем создав на нем подходящие индексы.

select cola, colb, colc, cold, ID 
INTO #PfTest 
FROM PfTest 

CREATE NONCLUSTERED INDEX IX_PFTEST1 ON #PfTest(id) INCLUDE (cola, colb, colc, cold) 
CREATE NONCLUSTERED INDEX IX_PFTEST2 ON #PfTest(colc) INCLUDE (cola, colb, id, cold) 
CREATE NONCLUSTERED INDEX IX_PFTEST3 ON #PfTest(cold) INCLUDE (cola, colb, id, colc) 

select cola, colb, colc, cold, ID 
from #PfTest 
WHERE colc In ('2014-01-01') 

INTERSECT 

select cola, colb, colc, cold, id 
from 

(select cola, colb, colc, cold, ID 
from #PfTest 

EXCEPT 


SELECT cola, colb, colc, cold, 1 id FROM #PfTest 
where 
colc IN('2014-01-02', '2014-01-03', 
           '2014-01-04', '2014-01-05', '2014-01-06'))A 

Используется EXCEPT вместо NOT IN, чтобы улучшить производительность немного.

+0

На какой таблице вы создали индекс? В таблице или таблице Temp? – MAK

+1

Типо. Починил это. – SouravA

+0

Yup! Это потрясающе. Большое вам спасибо – MAK

Смежные вопросы