Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Оптимизация запроса - план/факт продаж / 19 сообщений из 19, страница 1 из 1
06.11.2020, 12:58
    #40015911
Rgmffn
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Здравствуйте!

Прошу помощи у более опытных коллег.

Исходные данные:

Таблица данных продаж за пару лет
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE Receipts (
     [date] int,   -- дата YYYYMMDD
     [id_shop] int,   -- id магазина
     [id_good] int,   --id товара
     [sale] money   -- цена продажи
);


Таблица плана по продажам
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE Plan_sales (
     [date] int,   -- дата YYYYMMDD = (Receipts.[date]+10000)
     [id_shop] int,   -- id магазина
     [id_good] int,   --id товара
     [plan_sale] money   -- план продаж этого товара, устанавливается на тот же месяц следующего года
)



В результирующей таблице необходимо объединить данные:
[date], [id_shop], [id_good], [sale] - факт продаж товара, [plan_sale] - установленный план продаж, [sale_prev_year] - продажи этого товара в прошлом году.

Проблема заключается в слишком долгом выполнении запросов: я join'ю к таблице Receipts таблицу Plan_sales по столбцам
[date], [id_shop], [id_good], снова join'ю таблицу receipts для получения выручки [sale] за прошлый год,
и при небольшом итоговом количестве строк (~5k) время выполнения доходит до 6-7 минут.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select     [date]
             ,id_shop 
             ,id_good 
             ,sale
from [Receipts] as s
left join [Plan_sales] as p
     on s.date = p.date and s.id_shop = p.id_shop and s.id_good = p.id_good
left join [Receipts] as spy
     on s.date = spy.date+10000 and s.id_shop = spy.id_shop and s.id_good = spy.id_good



Кроме этих джойнов намечается ещё минимум три, справочная информация. Но уже на этом этапе процедура работает неудовлетворительно.

Подсказали, что в данной задаче необходимо использовать UNION ALL для оптимизации времени выполнения.
Непонятно, юнион чего с чем и, самое главное, для чего. Какие существуют подходы к решению подобных задач?
...
Рейтинг: 0 / 0
06.11.2020, 13:11
    #40015919
londinium
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
А индексы на этих таблицах есть?
...
Рейтинг: 0 / 0
06.11.2020, 13:13
    #40015920
Rgmffn
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
londinium,

да, обе таблицы имеют кластеризованный индекс по дате [date]
...
Рейтинг: 0 / 0
06.11.2020, 13:27
    #40015923
vikkiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
неплохо-бы по человечески алиасы поставить для каждого поля в select чтобы
не было проблем с выбором (из какого этапа join вытаскивать поле при их одинаковых названиях)

смотря что надо получить и в каком виде исходные данные,

если в Plan_sales записи уникальны - то про Receipts вовсе не факт
(тогда сначала возможно нужна предварительная агрегация)

так-же неизвестно полный-ли набор в Plan_sales или в Receipts есть комбинации которых нет в Plan_sales

union вероятно нужен для предварительного получения полного набора из обоих таблиц
(если результат нужен для идентификации проблем с любой стороны)

так-же при сдвиге по датам - нужны-ли устаревшие продукты в результате


ответы на эти вопросы не настолько очевидны, тут разве что двигаться на основе предположений (которые могут оказаться ошибочны)

это всё к тому что выражено проблемы с постановкой задачи/условиями (недостаток спецификации от которого зависит ход решения),
так что пока можно только предполагать наугад копая в случайные стороны.
...
Рейтинг: 0 / 0
06.11.2020, 13:29
    #40015925
Rgmffn
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Неточно описал запрос, ниже скорректирован:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select     s.[date]
             ,s.id_shop 
             ,s.id_good 
             ,s.sale
             ,p.plan_sale
             ,spy.sale
from [Receipts] as s
left join [Plan_sales] as p  --plan_sale текущий план на данный товар в данном магазине
     on s.date = p.date and s.id_shop = p.id_shop and s.id_good = p.id_good
left join [Receipts] as spy -- sale_previous_year продажи этого товара в этом магазине за этот месяц прошлого года
     on s.date = spy.date+10000 and s.id_shop = spy.id_shop and s.id_good = spy.id_good
...
Рейтинг: 0 / 0
06.11.2020, 13:40
    #40015931
Rgmffn
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
vikkiv,
vikkivсмотря что надо получить и в каком виде исходные данные,


Нужно получить сводную таблицу и в ней вычислить несколько доп.столбцов на основании данных sale, plan, sale_prev_year,
а именно, одно вычесть из другого, поделить итд (показатели выполнения плана)

vikkivесли в Plan_sales записи уникальны - то про Receipts вовсе не факт
(тогда сначала возможно нужна предварительная агрегация)
Да, там есть момент с агрегацией, но он выполнен шагом ранее и к нему вопросов нет.
Сейчас предполагается, что все значения уникальны.

vikkivтак-же неизвестно полный-ли набор в Plan_sales или в Receipts есть комбинации которых нет в Plan_sales
Набор неполный, на некоторые товары нет плана или "прошлого года"; в результирующей таблице будут NULL'ы по plan_sale и sale_prev_year (который spy.sale)

vikkivunion вероятно нужен для предварительного получения полного набора из обоих таблиц
(если результат нужен для идентификации проблем с любой стороны)
100% уникальность значений по ([date]-[id_shop]-[id_good]). Исходя из этого, я предполагаю, что нет разницы, какой юнион тут делать. Обычному Union нечего убирать из результата
vikkivнеплохо-бы по человечески алиасы поставить для каждого поля в select чтобы
не было проблем с выбором (из какого этапа join вытаскивать поле при их одинаковых названиях)
Добавил, сообщением ниже

Руководителем был забракован вариант внесения нескольких показателей в таблицу Plan_sales (я предполагал поместить туда и выручку, и план - и вот было бы готово уже два показателя: plan_sale и sale_prev_year, и джойна уже не два, а один). Руководителю я верю, значит, есть другой способ. Мне намекнули, что как-то надо использовать UNION (ALL).

Надеюсь, что смог добавить ясности..
...
Рейтинг: 0 / 0
06.11.2020, 13:47
    #40015936
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Rgmffn
londinium,

да, обе таблицы имеют кластеризованный индекс по дате [date]


а нужен такой {id_shop,id_good,date}

пс
в смысле, - дополнительно, ещё и такой индекс нужен
...
Рейтинг: 0 / 0
06.11.2020, 13:51
    #40015938
vikkiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Rgmffn
Набор неполный, на некоторые товары нет плана или "прошлого года"
надеюсь последствия такого подхода осознаются?
этом случае left (outer) join потеряет строки где есть план но с продажами у менеджеров не получилось..
т.е. кое-кто не понесёт ответственности за невыполнение "возложенных надежд"
...
Рейтинг: 0 / 0
06.11.2020, 13:51
    #40015940
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Rgmffn,

Код: sql
1.
2.
3.
4.
5.
set statistics xml on;

Ваш запрос

set statistics xml off;

Выполнить и выложить сюда получившийся xml в виде файла с расширением sqlplan
...
Рейтинг: 0 / 0
06.11.2020, 14:09
    #40015950
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Rgmffn
Проблема заключается в слишком долгом выполнении запросов: я join'ю к таблице Receipts таблицу Plan_sales по столбцам
[date], [id_shop], [id_good], снова join'ю таблицу receipts для получения выручки [sale] за прошлый год,
и при небольшом итоговом количестве строк (~5k) время выполнения доходит до 6-7 минут.
Понятное дело.
Индексы по дате, а в запросе есть даты, в том числе в условиях джойнов?
Вот оно и медленно.

Зачем по дате индексы сделали, секционирование? :-)
...
Рейтинг: 0 / 0
06.11.2020, 14:13
    #40015954
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
alexeyvg
Rgmffn
Проблема заключается в слишком долгом выполнении запросов: я join'ю к таблице Receipts таблицу Plan_sales по столбцам
[date], [id_shop], [id_good], снова join'ю таблицу receipts для получения выручки [sale] за прошлый год,
и при небольшом итоговом количестве строк (~5k) время выполнения доходит до 6-7 минут.
Понятное дело.
Индексы по дате, а в запросе есть даты, в том числе в условиях джойнов?
Вот оно и медленно.

Зачем по дате индексы сделали, секционирование? :-)
Во первых, кластерный индекс по
[date], [id_shop], [id_good]

Во вторых, поменяйте условие
s.date = spy.date+10000
на
s.date-10000 = spy.date
...
Рейтинг: 0 / 0
06.11.2020, 14:13
    #40015955
Rgmffn
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
invm,
...
Рейтинг: 0 / 0
06.11.2020, 14:16
    #40015957
Rgmffn
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
alexeyvg,

по дате необходим кластерный индекс, т.к. дата есть основной параметр для любых выборок из таблицы.
Процедура на вход получает даты, все факты идут по дате. А самое главное, руководитель сказал "делать по дате!")

Насколько я сейчас понимаю, в процессе выполнения этой задачи и должна (по "стажёрскому" сценарию) возникать такая проблема.
Намёк заключался в том, что необходимо использовать UNION ALL. Единственное, что здесь в принципе возможно заюнионить, - это выборка нужных мне продаж по дате, нужных мне планов по дате, нужных мне продаж за прошлый год по дате, из двух таблиц с выполняющимся дважды запросом к одной из них. И как-то хитро провести юнион, чтобы в итоге это выглядело как результат join'a (или не как результат join'a? я сам с этим не разобрался и до сих пор не получается)
...
Рейтинг: 0 / 0
06.11.2020, 15:54
    #40015992
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Rgmffn,

1. В плане совершенно другой запрос, а не тот, который было показан первоначально.
2. Из-за неверных оценок кардинальности получился кривой план. Поэтому, для начала, а) обновите статистику таблиц и б) добавьте к запросу option (recompile)
...
Рейтинг: 0 / 0
06.11.2020, 16:06
    #40016000
komrad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
invm
Rgmffn,

1. В плане совершенно другой запрос, а не тот, который было показан первоначально.
2. Из-за неверных оценок кардинальности получился кривой план. Поэтому, для начала, а) обновите статистику таблиц и б) добавьте к запросу option (recompile)

+ неплохо бы избавиться от @storeTable, если там не одна (сотня) записей
...
Рейтинг: 0 / 0
06.11.2020, 16:35
    #40016019
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
Код: sql
1.
2.
3.
4.
5.
6.
7.
left join [Receipts] as spy
on s.date = spy.date+10000 and 

-- заменить на

left join [Receipts] as spy
on s.date - 100000  = spy.date and 
...
Рейтинг: 0 / 0
06.11.2020, 16:43
    #40016021
komrad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
aleks222,

любопытно
а в чем будет практическая польза? мне для расширения кругозора

Код: sql
1.
2.
3.
4.
5.
6.
7.
left join [Receipts] as spy
on s.date = spy.date+10000 and 

-- заменить на

left join [Receipts] as spy
on s.date - 100000  = spy.date and 



...
Рейтинг: 0 / 0
06.11.2020, 17:08
    #40016035
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
komrad,

По s в текущем запросе и так идёт полное сканирование, поэтому проще посчитать скаляр s,date - 10000 и попытаться получить seek на spy, нежели отдать расчёт скаляра на этап извлечения данных из spy, где из-за этого расчёта скорее всего будет scan.
...
Рейтинг: 0 / 0
06.11.2020, 17:31
    #40016044
komrad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация запроса - план/факт продаж
env,

спасибо!
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Оптимизация запроса - план/факт продаж / 19 сообщений из 19, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]