Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Добрый день, коллеги.

Подскажите, пожалуйста, концептуально, каким образом мне оптимизировать запросы к БД?
Строк данных порядка 300 000. И есть ряд задач по агрегированию данных и их использованию в различных представлениях.
Запросы выполняются неприемлемо долго при созданных всех необходимых индексах. И для решения этой проблемы я пошел путем триггеров. Т.е. создал таблицы, в которых триггерами обновляются агрегированные данные. Такой подход меня сильно настораживает с точки зрения целостности данных.

Вопрос в том, какие в принципе есть решения по существенному ускорению работы с данными без костылей, как я придумал с триггерами?
15 апр 17, 16:25    [20404590]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
view,
Guest
Vsevolod V

Вопрос в том, какие в принципе есть решения по существенному ускорению работы с данными без костылей, как я придумал с триггерами?
инднксированные вью
15 апр 17, 17:20    [20404663]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Спасибо за ответ. Дайте, пожалуйста, больше информации. Я создал индексы по рекомендациям execution estimation plan. Соответственно, сейчас этот инструмент не дает больше информации об отсутствующих индексах. Получается, этого недостаточно? Это 100% верное решение? Я, разумеется, готов почитать по индексами, если это так. Дело в каких-то настройках индексов?
15 апр 17, 18:30    [20404745]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Критик
Member

Откуда: Москва / Калуга
Сообщений: 35399
Блог
если это аналитическая отчетность, то вам нужно переходить к DWH
15 апр 17, 18:55    [20404770]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Задача у меня для срм системы. Есть 300 000 контактов по клиентам, и требуется агрегировать данные по контактам для предоставления оперативной информации, какие контакты по каким задачам в рамках взаимоотношений с клиентами необходимо "сейчас" сделать менеджерам. Dwh не будет перебором для этой задачи?
15 апр 17, 19:07    [20404786]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2307
Vsevolod V,
Приведите структуру данных и пример запроса. Что то у вас ОЧЕНЬ неправильно - или структура данных, или запросы.
Любой не рассыпающийся от старости сервер легко обработает такие объемы данных. 300 тысяч - это очень мало.
15 апр 17, 21:49    [20404985]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Дедушка
Member

Откуда: Город трёх революций
Сообщений: 5126
Vsevolod V
Есть 300 000 контактов по клиентам, и требуется агрегировать данные по контактам
какие данные агрегируете и сколько их?
Vsevolod V
Запросы выполняются неприемлемо долго при созданных всех необходимых индексах
"долго" это сколько? пример запроса привести можете?
15 апр 17, 21:51    [20404989]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
s_ustinov
Vsevolod V,
Приведите структуру данных и пример запроса. Что то у вас ОЧЕНЬ неправильно - или структура данных, или запросы.
Любой не рассыпающийся от старости сервер легко обработает такие объемы данных. 300 тысяч - это очень мало.
Btw, всякое бывает. У меня вчера индекс на пустой таблице ребилдился три минуты. (Сервер и СХД от старовти не умирают).
15 апр 17, 21:56    [20404994]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2307
Гавриленко Сергей Алексеевич
s_ustinov
Vsevolod V,
Приведите структуру данных и пример запроса. Что то у вас ОЧЕНЬ неправильно - или структура данных, или запросы.
Любой не рассыпающийся от старости сервер легко обработает такие объемы данных. 300 тысяч - это очень мало.
Btw, всякое бывает. У меня вчера индекс на пустой таблице ребилдился три минуты. (Сервер и СХД от старовти не умирают).

Понятно, что случаи разные бывают. Но крайне маловероятно, что обработка 300 тысяч строк систематически тормозит по причине сложного алгоритма. Намного вероятнее, что или структура данных неоптимальная, или запросы кривые.
15 апр 17, 22:41    [20405033]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
view,
Guest
s_ustinov
Vsevolod V,
Приведите структуру данных ...

ставлю на EAV :)
15 апр 17, 23:14    [20405085]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Структура данных следующая.
t_A_Agent - клиенты
t_A_TaskType - план задач по клиентам (звонки, письма). Для статусов по клиентам настраиваются задачи, которые отображаются менеджерам. Если задание не выполнено и наступила дата этого задания, то менеджер должен его увидеть (это и есть основная задача запроса).
t_A_Contact - контакты по клиентам. Каждый контакт содержит ссылку на t_A_TaskType по primary key

t_A_Agent
a_id a_name s_id (код статуса клиента)
1 Вася 3
2 Петя 12


t_A_TaskType
tt_id s_id i_id_periodType (день час минута) tt_period tt_comment
1 3 3 5 Отправить КП
2 3 1 1 Позвонить после КП
3 3 1 2 Отправить Акцию
4 3 1 1 Позвонить после акции
5 12 3 1 Холодный звонок
16 апр 17, 10:22    [20405346]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Vsevolod V,

случайно отправилось. Еще не доделал пост
16 апр 17, 10:22    [20405348]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Структура данных следующая.
t_A_Agent - клиенты
t_A_TaskType - план задач по клиентам (звонки, письма). Для статусов по клиентам настраиваются задачи, которые отображаются менеджерам. Если задание не выполнено и наступила дата этого задания, то менеджер должен его увидеть (это и есть основная задача запроса).
t_A_Contact - контакты по клиентам. Каждый контакт содержит ссылку на t_A_TaskType по primary key

t_A_Agent
a_id a_name s_id (код статуса клиента)
1 Вася 3
2 Петя 12


t_A_TaskType
tt_id s_id i_id_periodType (день; час; минута) tt_period tt_comment tt_order (порядок задачи для статуса)
1 3 3 5 Отправить КП 1
2 3 1 1 Позвонить после КП2
3 3 1 2 Отправить Акцию3
4 3 1 1 Позвонить после акции4
5 12 3 1 Холодный звонок5


t_A_Contact
c_id tt_id a_id c_date c_nextDate c_taskCompleted c_comment
1 1 1 12.04.2017 13.04.2017 1 Отправил КП
2 2 1 13.04.2017 14.04.2017 0 Не дозвонился
3 2 1 14.04.2017 14.04.2017 1 КП презентовано. Готовы работать


v_A_TaskDone - Выполненные задания
SELECT        a_id, tt_id, ct_id
FROM            dbo.t_A_Contact
WHERE        (c_taskCompleted = 1)

v_A_TasksNotDone - невыполненные задания. Выбираются задания для статуса с наименьшим порядком. Запрос ко всей базе выполняется 6 секунд
SELECT        a.a_id, tt.i_id_source, iSource.i_name AS SourceName, tt.s_id, MIN(tt.tt_order) AS tt_order, a.u_id, tt.i_id_source2
                                 FROM            dbo.t_A_TaskType AS tt INNER JOIN
                                                           dbo.t_A_Agent AS a ON tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id INNER JOIN
                                                           dbo.t_CC_Task AS t ON a.t_id_calltask = t.t_id LEFT OUTER JOIN
                                                           dbo.v_A_TaskDone AS td ON tt.tt_id = td.tt_id AND a.a_id = td.a_id INNER JOIN
                                                           dbo.vLastContactDate AS lcd ON a.a_id = lcd.a_id INNER JOIN
                                                           dbo.t_A_Item AS iSource ON tt.i_id_source = iSource.i_id INNER JOIN
                                                           dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
                                 WHERE        (td.tt_id IS NULL) AND (CAST(tt.tt_startDate AS date) <= CAST(lcd.c_date AS date)) 
                                 GROUP BY a.a_id, tt.i_id_source, tt.s_id, a.u_id, iSource.i_name, tt.i_id_source2

vLastContactDate
SELECT        c_date, a_id, s_id
FROM            dbo.t_A_Contact AS c1
WHERE        (c_id =
                             (SELECT        MAX(c_id) AS Expr1
                               FROM            dbo.t_A_Contact AS c2
                               WHERE        (c1.a_id = a_id)
                               GROUP BY a_id))

v_A_Tasks. Текущие задачи по клиентам к выполнению. Запрос выполняется 30 секунд. В запросе реализована логика по отображению задач, которые по времени длолжны быть
выполнены сейчас
WITH taskData AS (SELECT        t.a_id, t1.tt_id, t1.i_id_source, t1.s_id, t1.tt_order, t1.ug_id, t1.tt_autosend, t1.m_id_template, t1.i_id_name, t1.i_id_periodType, t1.tt_period, 
                                                                   t1.i_id_contactType, NULL AS c_date, t.u_id, cmnd.c_nextDate, CASE WHEN isnull(cld.c_date, cmnd.c_nextDate) 
                                                                   <= cmnd.c_nextDate THEN cmnd.c_nextDate ELSE cld.c_date END AS startDatePoint, t1.tt_comment, 
                                                                   cndt.c_nextDate AS nextTaskContactDate
                                          FROM            dbo.v_A_TasksNotDone AS t INNER JOIN
                                                                   dbo.t_A_TaskType AS t1 ON t.i_id_source = t1.i_id_source AND t.s_id = t1.s_id AND t.tt_order = t1.tt_order LEFT OUTER JOIN
                                                                   dbo.v_A_ContactLastDateByTask AS cld ON t.a_id = cld.a_id AND t.s_id = cld.s_id AND t.i_id_source = cld.i_id_source LEFT OUTER JOIN
                                                                   dbo.v_A_ContactMaxNextDate AS cmnd ON t.a_id = cmnd.a_id LEFT OUTER JOIN
                                                                   dbo.v_A_ContactNextDateForTask AS cndt ON t1.tt_id = cndt.tt_id AND t.a_id = cndt.a_id)
    SELECT        a_id, tt_id, i_id_source, s_id, tt_order, ug_id, tt_autosend, m_id_template, i_id_name, i_id_periodType, tt_period, i_id_contactType, c_date, u_id, c_nextDate, 
                              tt_comment, nextTaskContactDate, CASE WHEN i_id_contactType = 2152 AND nextTaskContactDate IS NOT NULL 
                              THEN nextTaskContactDate ELSE CASE i_id_periodType WHEN 4176 THEN DATEADD(MI, tt_period, startDatePoint) WHEN 4177 THEN DATEADD(HH, tt_period, 
                              startDatePoint) WHEN 4178 THEN DATEADD(D, tt_period, CAST(startDatePoint AS date)) WHEN 4179 THEN DATEADD(WK, tt_period, CAST(startDatePoint AS date)) 
                              WHEN 4180 THEN DATEADD(M, tt_period, CAST(startDatePoint AS date)) END END AS taskDate
     FROM            taskData AS taskData_1
     WHERE        (CASE WHEN i_id_contactType = 2152 AND nextTaskContactDate IS NOT NULL 
                              THEN nextTaskContactDate ELSE CASE i_id_periodType WHEN 4176 THEN DATEADD(MI, tt_period, startDatePoint) WHEN 4177 THEN DATEADD(HH, tt_period, 
                              startDatePoint) WHEN 4178 THEN DATEADD(D, tt_period, CAST(startDatePoint AS date)) WHEN 4179 THEN DATEADD(WK, tt_period, CAST(startDatePoint AS date)) 
                              WHEN 4180 THEN DATEADD(M, tt_period, CAST(startDatePoint AS date)) ELSE getdate() - 1 END END < GETDATE())

v_A_ContactLastDateByTask
SELECT        c.a_id, c.s_id, a.i_id_source, MAX(c.c_date) AS c_date
FROM            dbo.t_A_Contact AS c INNER JOIN
                         dbo.t_A_Agent AS a ON c.a_id = a.a_id
GROUP BY c.a_id, c.s_id, a.i_id_source

v_A_ContactMaxNextDate
SELECT        c.a_id, MAX(c.c_nextDate) AS c_nextDate
FROM            dbo.t_A_Contact AS c INNER JOIN
                         dbo.t_A_Agent AS a ON c.a_id = a.a_id
GROUP BY c.a_id

v_A_ContactNextDateForTask
SELECT        a_id, MAX(c_nextDate) AS c_nextDate, tt_id
FROM            dbo.t_A_Contact AS m
WHERE        (ISNULL(c_taskCompleted, 0) = 0) AND (tt_id IS NOT NULL)
GROUP BY a_id, tt_id
16 апр 17, 10:47    [20405384]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
Понимаю, что причина тормозов во вьюшках. Но не понимаю, каким образом оптимизировать их. Поэтому для представлений, перечисленных ниже, сделал статичные таблицы и обновляю их триггерами.
vLastContactDate, v_A_TaskDone, v_A_ContactLastDateByTask, v_A_ContactMaxNextDate, v_A_ContactNextDateForTask

Помогите, пожалуйста, разобраться, как правильно построить запросы, если такая возможность есть.
16 апр 17, 10:57    [20405396]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
aleks2
Guest
Vsevolod V
Понимаю, что причина тормозов во вьюшках. Но не понимаю, каким образом оптимизировать их.

Помогите, пожалуйста, разобраться, как правильно построить запросы, если такая возможность есть.


1. Не надо пихать под группировку 100500 join-ов. И будет тебе щастье.
16 апр 17, 11:44    [20405460]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
aleks2
Guest
v_A_TasksNotDone - невыполненные задания. Выбираются задания для статуса с наименьшим порядком. Запрос ко всей базе выполняется 6 секунд
SELECT        a.a_id, tt.i_id_source, iSource.i_name AS SourceName, tt.s_id, MIN(tt.tt_order) AS tt_order, a.u_id, tt.i_id_source2
                                 FROM            dbo.t_A_TaskType AS tt INNER JOIN
                                                           dbo.t_A_Agent AS a ON tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id INNER JOIN
                                                           dbo.t_CC_Task AS t ON a.t_id_calltask = t.t_id LEFT OUTER JOIN
                                                           dbo.v_A_TaskDone AS td ON tt.tt_id = td.tt_id AND a.a_id = td.a_id INNER JOIN
                                                           dbo.vLastContactDate AS lcd ON a.a_id = lcd.a_id INNER JOIN
                                                           dbo.t_A_Item AS iSource ON tt.i_id_source = iSource.i_id INNER JOIN
                                                           dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
                                 WHERE        (td.tt_id IS NULL) AND (CAST(tt.tt_startDate AS date) <= CAST(lcd.c_date AS date)) 
                                 GROUP BY a.a_id, tt.i_id_source, tt.s_id, a.u_id, iSource.i_name, tt.i_id_source2

Пример незамутненного бреда.

1. Нафига под группировку запихнуто dbo.t_A_Item AS iSource ON tt.i_id_source = iSource.i_id ? Сначала сгруппирой - потом присоедини.
2. Въюха, да еще и с группировкой dbo.vLastContactDate AS lcd ON a.a_id = lcd.a_id - это отстой.

with x as (
SELECT a.a_id, tt.i_id_source, tt.s_id, MIN(tt.tt_order) AS tt_order, a.u_id, tt.i_id_source2
FROM dbo.t_A_TaskType AS tt INNER JOIN
dbo.t_A_Agent AS a ON tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id INNER JOIN
dbo.t_CC_Task AS t ON a.t_id_calltask = t.t_id LEFT OUTER JOIN
dbo.v_A_TaskDone AS td ON tt.tt_id = td.tt_id AND a.a_id = td.a_id
-- INNER JOIN dbo.vLastContactDate AS lcd ON a.a_id = lcd.a_id
cross apply ( select top(1) c_date from dbo.t_A_Contact where a_id = a.a_id order by c_id desc ) as lcd
INNER JOIN dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
WHERE (td.tt_id IS NULL) AND (CAST(tt.tt_startDate AS date) <= CAST(lcd.c_date AS date))
GROUP BY a.a_id, tt.i_id_source, tt.s_id, a.u_id, tt.i_id_source2
)
select *, iSource.i_name AS SourceName from x left outer join dbo.t_A_Item AS iSource ON x.i_id_source = iSource.i_id;

Даже столь незначительные изменения сделают запрос быстрее раза в два.
А поскоку таких "в два раза" там раза четыре => ускорить раз в 16 - как нефиг делать.
16 апр 17, 12:25    [20405504]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
aleks2
2. Въюха, да еще и с группировкой dbo.vLastContactDate AS lcd ON a.a_id = lcd.a_id - это отстой.

Спасибо за ответ.
А вью dbo.v_A_TaskDone не является проблемой?
И еще. Вы предложили использование cross apply. А не будет ли эффективнее использовать скалярную функцию?
...
WHERE        (td.tt_id IS NULL) AND (CAST(tt.tt_startDate AS date) <= dbo.fn_GetLastContactDate(...)) 
16 апр 17, 13:14    [20405575]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Сид
Member

Откуда: Москва
Сообщений: 305
Vsevolod V,

CAST(tt.tt_startDate AS date) <= CAST(lcd.c_date AS date)

Больно на это смотреть!
Вижу 2 варианта (нужно выбрать 1 по итогам тестов на реальных данных):
1) tt.tt_startDate < CAST(lcd.c_date+1 AS date)
2) lcd.c_date>=CAST(tt.tt_startDate AS date)
3) завести для этих дат отдельные поля без времени и сравнивать без CAST вообще. И не забыть про индексы, конечно.

Ибо преобразования в блоке WHERE - очень, очень, очень плохо для сервера!

WHERE  (CASE WHEN i_id_contactType = 2152 AND nextTaskContactDate IS NOT NULL THEN nextTaskContactDate
	ELSE
		CASE i_id_periodType
		WHEN 4176 THEN DATEADD(MI, tt_period, startDatePoint)
		WHEN 4177 THEN DATEADD(HH, tt_period, startDatePoint)
		WHEN 4178 THEN DATEADD(D, tt_period, CAST(startDatePoint AS date))
		WHEN 4179 THEN DATEADD(WK, tt_period, CAST(startDatePoint AS date)) 
                WHEN 4180 THEN DATEADD(M, tt_period, CAST(startDatePoint AS date))
		ELSE getdate() - 1
		END
	END < GETDATE())


Кровь из глаз! Этот блок, наверное, даёт больше всего тормозов. Решение: заранее рассчитать время планируемого окончания задачи (весь этот блок CASE), засунуть полем в таблицу, и тупо сравнивать с getdate(). И не забыть про индекс, конечно.
16 апр 17, 13:31    [20405594]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
По вашим комментариям отредактировал вьюшки v_A_TasksNotDone и v_A_Tasks. Вью v_A_Tasks выполняется 2-4 секунды и возвращает 3800 строк. Подскажите, пожалуйста, есть ли еще варианты пущей оптимизации запросов?

v_A_TasksNotDone
with x as (
SELECT a.a_id, tt.i_id_source, tt.s_id, MIN(tt.tt_order) AS tt_order, a.u_id, tt.i_id_source2,
CASE WHEN ISNULL(t.i_id_status, 0) = 2 AND a.s_id IN (13, 14) THEN 0 ELSE 1 END baseStatus
FROM dbo.t_A_TaskType AS tt INNER JOIN
dbo.t_A_Agent AS a ON tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id INNER JOIN
dbo.t_CC_Task AS t ON a.t_id_calltask = t.t_id LEFT OUTER JOIN
dbo.v_A_TaskDone AS td ON tt.tt_id = td.tt_id AND a.a_id = td.a_id 
cross apply (select top(1) c_date from dbo.t_A_Contact where a_id = a.a_id order by c_id desc) as lcd
INNER JOIN dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
WHERE (td.tt_id IS NULL) AND (p.i_id_status = 20) 

AND (tt.tt_startDate <= lcd.c_date or tt.tt_startDate IS NULL)
GROUP BY a.a_id, tt.i_id_source, tt.s_id, a.u_id, tt.i_id_source2, t.i_id_status, a.s_id
)
select *, iSource.i_name AS SourceName from x left outer join dbo.t_A_Item AS iSource ON x.i_id_source = iSource.i_id
where baseStatus = 1


v_A_Tasks
WITH taskData AS (SELECT  t.a_id, t1.tt_id, t1.i_id_source, t1.s_id, t1.tt_order, t1.ug_id, t1.tt_autosend, t1.m_id_template, t1.i_id_name, 
t1.i_id_periodType, t1.tt_period, t1.i_id_contactType, t.u_id, cld.c_date,  cld2.c_nextDate, t1.tt_comment,isnull(cld2.c_nextDate, cld.c_date) AS startDatePoint,
CASE WHEN i_id_contactType = 2152 AND cld2.c_nextDate IS NOT NULL 
THEN cld2.c_nextDate 
ELSE 
	CASE i_id_periodType 
	WHEN 4176 THEN DATEADD(MI, tt_period, isnull(cld2.c_nextDate, cld.c_date)) 
	WHEN 4177 THEN DATEADD(HH, tt_period, isnull(cld2.c_nextDate, cld.c_date)) 
	WHEN 4178 THEN DATEADD(D, tt_period, CAST(isnull(cld2.c_nextDate, cld.c_date) AS date)) 
	WHEN 4179 THEN DATEADD(WK, tt_period, CAST(isnull(cld2.c_nextDate, cld.c_date) AS date)) 
	WHEN 4180 THEN DATEADD(M, tt_period, CAST(isnull(cld2.c_nextDate, cld.c_date) AS date)) END END taskDate

FROM dbo.v_A_TasksNotDone2 AS t INNER JOIN
dbo.t_A_TaskType AS t1 ON t.i_id_source = t1.i_id_source AND t.s_id = t1.s_id AND t.tt_order = t1.tt_order 
outer apply dbo.fn_GetLastContactDate(t.a_id, isnull(t1.i_id_grouping, 0)) cld
outer apply dbo.fn_GetMaxNextDate(t.a_id, isnull(t1.i_id_grouping, 0)) cld2
                                          )
    SELECT        *
     FROM            taskData 
     WHERE        taskDate < GETDATE()
16 апр 17, 15:08    [20405650]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
aleks2
Guest
Стисняюся спросить: нафига ваще в v_A_TasksNotDone группировка?
16 апр 17, 20:45    [20405971]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
aleks2
Стисняюся спросить: нафига ваще в v_A_TasksNotDone группировка?

С удовольствием от нее откажусь! -)
Подскажите, пожалуйста, каким образом можно перестроить запрос? Необходимо выбрать невыполненное задание по клиенту с минимальным порядком tt_order. Тоже через табличную функцию?
17 апр 17, 09:44    [20406665]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
aleks2
Guest
Vsevolod V
aleks2
Стисняюся спросить: нафига ваще в v_A_TasksNotDone группировка?

С удовольствием от нее откажусь! -)
Подскажите, пожалуйста, каким образом можно перестроить запрос? Необходимо выбрать невыполненное задание по клиенту с минимальным порядком tt_order. Тоже через табличную функцию?


Мне не видно, чего вы там в "табличных функциях ваяете", но всяко это не повод для группировки.

SELECT a.a_id, tt.i_id_source, tt.s_id, MIN(tt.tt_order) AS tt_order, a.u_id, tt.i_id_source2,
CASE WHEN ISNULL(t.i_id_status, 0) = 2 AND a.s_id IN (13, 14) THEN 0 ELSE 1 END baseStatus
FROM dbo.t_A_TaskType AS tt INNER JOIN
dbo.t_A_Agent AS a ON tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id INNER JOIN
dbo.t_CC_Task AS t ON a.t_id_calltask = t.t_id LEFT OUTER JOIN
dbo.v_A_TaskDone AS td ON tt.tt_id = td.tt_id AND a.a_id = td.a_id 
cross apply (select top(1) c_date from dbo.t_A_Contact where a_id = a.a_id order by c_id desc) as lcd
INNER JOIN dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
WHERE (td.tt_id IS NULL) AND (p.i_id_status = 20) 

AND (tt.tt_startDate <= lcd.c_date or tt.tt_startDate IS NULL)
GROUP BY a.a_id, tt.i_id_source, tt.s_id, a.u_id, tt.i_id_source2, t.i_id_status, a.s_id



select a.a_id, tt.i_id_source, tt.s_id, tt.tt_order, a.u_id, tt.i_id_source2,
  FROM dbo.t_A_Agent AS a 
       inner join dbo.t_CC_Task AS t ON t.t_id = a.t_id_calltask
       cross apply (select top(1) c_date from dbo.t_A_Contact where a_id = a.a_id order by c_id desc) as lcd
       cross apply ( select top(1) * from dbo.t_A_TaskType AS tt
                                                       inner join dbo.t_CC_Project AS p ON p.i_id_name = tt.i_id_source
                       where tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id and (p.i_id_status = 20)
                             and not exists( select * from dbo.v_A_TaskDone where tt_id = tt.tt_id AND a_id = a.a_id )
                       order by tt.tt_order asc
                   ) as tt
17 апр 17, 10:18    [20406771]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
aleks2
Guest
Пардон, даты забыл

select a.a_id, tt.i_id_source, tt.s_id, tt.tt_order, a.u_id, tt.i_id_source2,
  FROM dbo.t_A_Agent AS a 
       inner join dbo.t_CC_Task AS t ON t.t_id = a.t_id_calltask
       cross apply (select top(1) c_date from dbo.t_A_Contact where a_id = a.a_id order by c_id desc) as lcd
       cross apply ( select top(1) * from dbo.t_A_TaskType AS tt
                                                       inner join dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
                       where tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id and (p.i_id_status = 20)
                             and (tt.tt_startDate <= lcd.c_date or tt.tt_startDate IS NULL)
                             and not exists( select * from dbo.v_A_TaskDone where tt_id = tt.tt_id AND a_id = a.a_id )
                       order by tt.tt_order asc
                   ) as tt
17 апр 17, 10:27    [20406800]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
StarikNavy
Member

Откуда: Москва
Сообщений: 2415
Vsevolod V
С создал индексы по рекомендациям execution estimation plan. Соответственно, сейчас этот инструмент не дает больше информации об отсутствующих индексах. Получается, этого недостаточно? в?

чаще всего да, недостаточно
просто подсказка от системы (про видимую верхушку айсберга)
17 апр 17, 10:42    [20406857]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запросов к большим массивам данных  [new]
Vsevolod V
Member

Откуда: Россия. Санкт-Петербург
Сообщений: 3194
aleks2
Пардон, даты забыл

select a.a_id, tt.i_id_source, tt.s_id, tt.tt_order, a.u_id, tt.i_id_source2,
  FROM dbo.t_A_Agent AS a 
       inner join dbo.t_CC_Task AS t ON t.t_id = a.t_id_calltask
       cross apply (select top(1) c_date from dbo.t_A_Contact where a_id = a.a_id order by c_id desc) as lcd
       cross apply ( select top(1) * from dbo.t_A_TaskType AS tt
                                                       inner join dbo.t_CC_Project AS p ON tt.i_id_source = p.i_id_name
                       where tt.i_id_source = a.i_id_source AND tt.s_id = a.s_id and (p.i_id_status = 20)
                             and (tt.tt_startDate <= lcd.c_date or tt.tt_startDate IS NULL)
                             and not exists( select * from dbo.v_A_TaskDone where tt_id = tt.tt_id AND a_id = a.a_id )
                       order by tt.tt_order asc
                   ) as tt


Спасибо за ответ. По поводу табличной функции вопрос в том, есть ли смысл выносить предложенные вами вложенные подзапросы в табличные функции. В моем понимании это будет одно и тоже, только код более читабельный. Или это тоже замедлит время выполнения?
17 апр 17, 11:29    [20407037]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить