Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

MSSQL. Посоветуйте индексы на таблицу   Найти похожие ветки 

 
AV ©   (2012-10-19 11:31) [0]

Таблицы большая. Широкая и длинная. Индексов сейчас никаких.
Запрос к ней один, ниже.
Каждый день добавляются строки (несколько десятков тысяч)
Каждый день получаю письмо, где написано время начала и конца запроса.
В первый день запрос идет несколько минут
Потом по нарастающей. К концу месяца не укладывается в ночь.
В начале следующего месяца таблица очищается до 0.
Задача - уложится в ночь.
Запрос не мой, что он делает - не знаю.
Как думаю - надо "правильно" навесить индексы.

SELECT
 MAX(t.[ANI]) Calling,
 RIGHT(MAX(case when t.[CallDisposition]  = 15 then t.[DigitsDialed] else null end), 10) Called,
 (select
     max(ct.[TalkTime])
   from filials_PureDD ct
   where ct.RecoveryKey = MAX(t.RecoveryKey))
     - SUM(case
            when t.[CallDisposition] = 15 then (t.[TalkTime]+t.[DelayTime])
            when t.[CallDisposition] in (28,29) then t.[TalkTime]
            else 0 end
   ) Duration,
  MAX(case when t.[CallDisposition]  = 15 then t.[DateTime] else null end) BeginCall,
  (select top 1 id_sct from ccc.dbo.sct where CallTypeID = MAX(t.[CallTypeID])) ID_SCT,
  MAX(t.[CallTypeID])  [CallTypeID],
  1 as StringForWrite
FROM filials_PureDD t
    join filials_PureDD tt
      on tt.RouterCallKeyDay = t.RouterCallKeyDay and tt.RouterCallKey = t.RouterCallKey
   
where t.[DateTime] >= :DTF
     and tt.[DateTime] <= :DTS
  and t.RouterCallKey <> 0
  and t.RouterCallKeyDay <> 0
  and tt.RouterCallKey <> 0
  and tt.RouterCallKeyDay <> 0
  and tt.CallDisposition=15
group by t.RouterCallKeyDay, t.RouterCallKey


 
AV ©   (2012-10-19 11:52) [1]

DateTime            datetime
RouterCallKey      int
RouterCallKeyDay int
CallTypeID          int
TalkTime            datetime
ANI                   varchar(32)


 
RWolf ©   (2012-10-19 11:56) [2]

ну, напрашиваются индексы на t.RouterCallKeyDay, t.RouterCallKey, раз уж группировка по ним идёт.
индекс на CallDisposition тоже не помешает.


 
AV ©   (2012-10-19 12:13) [3]

>> напрашиваются индексы на t.RouterCallKeyDay, t.RouterCallKey,
тоже думаю
а какие? простые?

+ я пока на DateTime простой ASC повесил

проблема еще в том, что сейчас почти "начало месяца"(там свое исчисление) и таблица почти пуста, едва сотня тысяч записей есть


 
AV ©   (2012-10-19 12:24) [4]

повесил
что имеею (если облажается - не виноват)
 |--Compute Scalar(DEFINE:([Expr1012]=right([Expr1007],(10)), [Expr1018]=[Expr1016]-[Expr1009], [ccc].[dbo].[sct].[id_sct]=[ccc].[dbo].[sct].[id_sct], [Expr1024]=(1)))
      |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Expr1011]))
           |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Expr1008]))
           |    |--Compute Scalar(DEFINE:([Expr1009]=CASE WHEN [Expr1045]=(0) THEN NULL ELSE [Expr1046] END))
           |    |    |--Stream Aggregate(GROUP BY:([t].[RouterCallKey], [t].[RouterCallKeyDay]) DEFINE:([Expr1006]=MAX([ccc].[dbo].[filials_PureDD].[ANI] as [t].[ANI]), [Expr1007]=MAX([Expr1027]), [Expr1008]=MAX([ccc].[dbo].[filials_PureDD].[RecoveryKey] as [t].[RecoveryKey]), [Expr1045]=COUNT_BIG([Expr1028]), [Expr1046]=SUM([Expr1028]), [Expr1010]=MAX([Expr1029]), [Expr1011]=MAX([ccc].[dbo].[filials_PureDD].[CallTypeID] as [t].[CallTypeID])))
           |    |         |--Sort(ORDER BY:([t].[RouterCallKey] ASC, [t].[RouterCallKeyDay] ASC))
           |    |              |--Filter(WHERE:([ccc].[dbo].[filials_PureDD].[RouterCallKeyDay] as [tt].[RouterCallKeyDay]=[ccc].[dbo].[filials_PureDD].[RouterCallKeyDay] as [t].[RouterCallKeyDay] AND [ccc].[dbo].[filials_PureDD].[DateTime] as [tt].[DateTime]<=getdate()-"1900-01-02 00:00:00.000" AND [ccc].[dbo].[filials_PureDD].[CallDisposition] as [tt].[CallDisposition]=(15) AND [ccc].[dbo].[filials_PureDD].[RouterCallKeyDay] as [tt].[RouterCallKeyDay]<>(0)))
           |    |                   |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1003], [Expr1044]) WITH UNORDERED PREFETCH)
           |    |                        |--Nested Loops(Inner Join, OUTER REFERENCES:([t].[RouterCallKey]) OPTIMIZED)
           |    |                        |    |--Compute Scalar(DEFINE:([Expr1027]=CASE WHEN [ccc].[dbo].[filials_PureDD].[CallDisposition] as [t].[CallDisposition]=(15) THEN [ccc].[dbo].[filials_PureDD].[DigitsDialed] as [t].[DigitsDialed] ELSE NULL END, [Expr1028]=CASE WHEN [ccc].[dbo].[filials_PureDD].[CallDisposition] as [t].[CallDisposition]=(15) THEN [ccc].[dbo].[filials_PureDD].[TalkTime] as [t].[TalkTime]+[ccc].[dbo].[filials_PureDD].[DelayTime] as [t].[DelayTime] ELSE CASE WHEN [ccc].[dbo].[filials_PureDD].[CallDisposition] as [t].[CallDisposition]=(29) OR [ccc].[dbo].[filials_PureDD].[CallDisposition] as [t].[CallDisposition]=(28) THEN [ccc].[dbo].[filials_PureDD].[TalkTime] as [t].[TalkTime] ELSE (0) END END, [Expr1029]=CASE WHEN [ccc].[dbo].[filials_PureDD].[CallDisposition] as [t].[CallDisposition]=(15) THEN [ccc].[dbo].[filials_PureDD].[DateTime] as [t].[DateTime] ELSE NULL END))
           |    |                        |    |    |--Filter(WHERE:(([ccc].[dbo].[filials_PureDD].[RouterCallKey] as [t].[RouterCallKey]<(0) OR [ccc].[dbo].[filials_PureDD].[RouterCallKey] as [t].[RouterCallKey]>(0)) AND ([ccc].[dbo].[filials_PureDD].[RouterCallKeyDay] as [t].[RouterCallKeyDay]<(0) OR [ccc].[dbo].[filials_PureDD].[RouterCallKeyDay] as [t].[RouterCallKeyDay]>(0))))
           |    |                        |    |         |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
           |    |                        |    |              |--Index Seek(OBJECT:([ccc].[dbo].[filials_PureDD].[IX_filials_PureDD_DateTime] AS [t]), SEEK:([t].[DateTime] >= getdate()) ORDERED FORWARD)
           |    |                        |    |              |--RID Lookup(OBJECT:([ccc].[dbo].[filials_PureDD] AS [t]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)
           |    |                        |    |--Index Seek(OBJECT:([ccc].[dbo].[filials_PureDD].[IX_filials_PureDD_RouterCallKey] AS [tt]), SEEK:([tt].[RouterCallKey]=[ccc].[dbo].[filials_PureDD].[RouterCallKey] as [t].[RouterCallKey]),  WHERE:([ccc].[dbo].[filials_PureDD].[RouterCallKey] as [tt].[RouterCallKey]<>(0)) ORDERED FORWARD)
           |    |                        |--RID Lookup(OBJECT:([ccc].[dbo].[filials_PureDD] AS [tt]), SEEK:([Bmk1003]=[Bmk1003]) LOOKUP ORDERED FORWARD)
           |    |--Stream Aggregate(DEFINE:([Expr1016]=MAX([ccc].[dbo].[filials_PureDD].[TalkTime] as [ct].[TalkTime])))
           |         |--Table Scan(OBJECT:([ccc].[dbo].[filials_PureDD] AS [ct]), WHERE:([ccc].[dbo].[filials_PureDD].[RecoveryKey] as [ct].[RecoveryKey]=[Expr1008]))
           |--Top(TOP EXPRESSION:((1)))
                |--Index Seek(OBJECT:([ccc].[dbo].[sct].[IX_CallType]), SEEK:([ccc].[dbo].[sct].[CallTypeID]=[Expr1011]) ORDERED FORWARD)


 
картман ©   (2012-10-19 19:49) [5]

- SUM(case
           when t.[CallDisposition] = 15 then (t.[TalkTime]+t.[DelayTime])
           when t.[CallDisposition] in (28,29) then t.[TalkTime]
           else 0 end
  ) Duration

я б вычисляемое поле сделал


 
знайка   (2012-10-19 19:56) [6]

А Advisor что говорит?


 
Kerk ©   (2012-10-19 22:15) [7]

http://sqloptimizersqlserver.inside.quest.com/ попробуй :)


 
AV ©   (2012-10-22 08:57) [8]


> Advisor что говорит?

Да тоже и говорит, только больше индексов хочет
НО, имхо, пока нет его смысла слушать. Данных мало, и что он выберет, то не будет оптимальным к концу месяца.

и по той же причине, не доверяю

> Kerk ©   (19.10.12 22:15) [7]


Тут надо эмпирически понять, прочувствовать объемы вперед

пока имею
старт всегда в 0:25:00
20.10.2012 0:28:59  Экспорт закончен
21.10.2012 0:29:37  Экспорт закончен
22.10.2012 - сегодня данных нет, БД отвалилась
(PureDD - это данные с удаленной БД, сегодня линк свалился)

Пока результаты сравнимы с тем, что было


 
AV ©   (2012-10-22 09:02) [9]


> PureDD - это данные с удаленной БД,

т.е. они локальны, таблица тут. Только подтягиваются непосредственно перед выборкой. Пробовал сразу с удаленного запрашивать - вообще, мрак. Уже в середине месяца можно не дождаться.
Соответственно, там я не админ, сделать ничего не могу. Решил тянуть сюда, а тут уже химичить.


 
AV ©   (2012-10-22 09:04) [10]


> - SUM(case
>            when t.[CallDisposition] = 15 then (t.[TalkTime]+t.
> [DelayTime])
>            when t.[CallDisposition] in (28,29) then t.[TalkTime]
>            else 0 end
>   ) Duration
>
> я б вычисляемое поле сделал

меня смущают магические цифры
что-то поменяется - потом не вспомнишь
а пока их видно явно


 
MsGuns ©   (2012-10-22 10:46) [11]

Если еще не все забыл.. Мы вроде избегали конструкции типа Select ...,select
заменяя их на select ... join (select ...) ...


 
AV ©   (2012-10-22 12:49) [12]


> MsGuns ©   (22.10.12 10:46) [11]

да..
и вообще тяжело понимать конструкции типа Select ...,select
но работает, заказчика устраивает - лучше не трогать..
сейчас не дай bug что сломается
..табла вообще 3 раза сама с собой пересекается, это не нормально, по-логике то

и вообще боюсь начинать разбираться что там написано..
>   select ... from ccc.dbo.sct
> Эт куда, что там? дока есть?
> Вот только ничего не спрашивай
> Я не знаю
> запрос их программа выполняет.
> писал им Костя перед увольнением
> Свяжись с ним, может пояснит

Проще подойти к вопросу механически и выполнить тз в рамках постановки - экспорт должен заканчиваться до 8-00. Пусть так и будет. Не будет - буду разбираться далее.


 
stone   (2012-10-22 14:57) [13]


> from filials_PureDD ct
>    where ct.RecoveryKey = MAX(t.RecoveryKey))
>      - SUM(case
>             when t.[CallDisposition] = 15 then (t.[TalkTime]+t.
> [DelayTime])
>             when t.[CallDisposition] in (28,29) then t.[TalkTime]
>
>             else 0 end


С такими конструкциями индекс не поможет


 
AV ©   (2012-10-23 03:42) [14]

Stop at 23.10.2012 0:32:10
в таблице 1182684 записей


 
AV ©   (2012-10-24 08:24) [15]

Stop at 24.10.2012 0:32:42
в таблице 1437130 записей

А может и пойдет все
+30 секунд, на +250 000 записей

тз из двух частей, правда, было
минимум озвучен
максимум - всегда в таблице есть записи за последний месяц + неделя
т.е. за последние примерно 40 дней.
Сегодня день 7ой, запрос идет примерно 7 минут


 
wicked ©   (2012-10-24 11:09) [16]

я бы подошел так:
1 - в начале, середине и в конце "периода" сделать копию таблицы - для того, чтобы можно было прогнать запросы на разных обьемах

2 - со всех копий сделать отчет вот этим страшным запросом - чтобы было понятно, корректно работает новый запрос или нет

3 - оптимизировать запрос до одурения
- убрать лишний join на tt (или обосновать для себя, зачем он нужен);
- поубирать выражения и вызовы функций в секции where - по ним оптимизатор не может применить индекс, даже если он есть;
- проставить индекса на все поля, которые участвуют в join-ах и where
- возможно, проставить filtered index (что то такое в mssql 2008 выдало по запросу conditional index) для тех полей, где много неиспользованых значений (нули в RouterCallKey и RouterCallKeyDay)


 
stone   (2012-10-24 11:49) [17]


> - проставить индекса на все поля, которые участвуют в join-
> ах и where

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


 
AV ©   (2012-10-24 12:00) [18]

а в сабже, скорее расчет по средневзвешенной
есть такая.
Хотя, имхо, спорная. Но так работают.


 
AV ©   (2012-10-24 12:09) [19]

не сюда :(

Спасибо.

Придется, видимо, понимать что там и зачем.

Или выделить еще одну таблицу, с данными 2-3 дней, по которой будет идти запрос этого отчета.
А все остальные данные, обозвать архивные, и хранить  в другой таблице.
И сделать вьюшку, как union этих таблиц


 
AV ©   (2012-10-24 12:18) [20]

т.е. мысль разовью.

where t.[DateTime] >= :DTF
    and tt.[DateTime] <= :DTS

:DTF и :DTS
по логу, постоянно требуется за последние сутки
реже, двое суток.
Пусть это будет оперативная таблица
Или Оперативная пусть будет как сейчас, неделя.

Остальное пусть в архивной будет.
Вьюшку обозвать как таблица называется сейчас. Кто захочет покопаться - пусть копается. Внешне разницы не будет.
Так даже можно за 2-3 месяца хранить.



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.06 c
15-1352536128
alexdn
2012-11-10 12:28
2013.03.22
asp.net


15-1342778707
Юрий Зотов
2012-07-20 14:05
2013.03.22
Наш ответ


2-1338443775
Demo
2012-05-31 09:56
2013.03.22
Настроить Delphi 2007


2-1334343958
vegarulez
2012-04-13 23:05
2013.03.22
[Free CreateOLEObject] Как?


6-1261579139
ZV
2009-12-23 17:38
2013.03.22
Client и Server. Как сделать надежно и просто ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский