|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Здравствуйте! Прошу помощи у более опытных коллег. Исходные данные: Таблица данных продаж за пару лет Код: sql 1. 2. 3. 4. 5. 6.
Таблица плана по продажам Код: sql 1. 2. 3. 4. 5. 6.
В результирующей таблице необходимо объединить данные: [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.
Кроме этих джойнов намечается ещё минимум три, справочная информация. Но уже на этом этапе процедура работает неудовлетворительно. Подсказали, что в данной задаче необходимо использовать UNION ALL для оптимизации времени выполнения. Непонятно, юнион чего с чем и, самое главное, для чего. Какие существуют подходы к решению подобных задач? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 12:58 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
А индексы на этих таблицах есть? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:11 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
londinium, да, обе таблицы имеют кластеризованный индекс по дате [date] ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:13 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
неплохо-бы по человечески алиасы поставить для каждого поля в select чтобы не было проблем с выбором (из какого этапа join вытаскивать поле при их одинаковых названиях) смотря что надо получить и в каком виде исходные данные, если в Plan_sales записи уникальны - то про Receipts вовсе не факт (тогда сначала возможно нужна предварительная агрегация) так-же неизвестно полный-ли набор в Plan_sales или в Receipts есть комбинации которых нет в Plan_sales union вероятно нужен для предварительного получения полного набора из обоих таблиц (если результат нужен для идентификации проблем с любой стороны) так-же при сдвиге по датам - нужны-ли устаревшие продукты в результате ответы на эти вопросы не настолько очевидны, тут разве что двигаться на основе предположений (которые могут оказаться ошибочны) это всё к тому что выражено проблемы с постановкой задачи/условиями (недостаток спецификации от которого зависит ход решения), так что пока можно только предполагать наугад копая в случайные стороны. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:27 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Неточно описал запрос, ниже скорректирован: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:29 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
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). Надеюсь, что смог добавить ясности.. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:40 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Rgmffn londinium, да, обе таблицы имеют кластеризованный индекс по дате [date] а нужен такой {id_shop,id_good,date} пс в смысле, - дополнительно, ещё и такой индекс нужен ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:47 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Rgmffn Набор неполный, на некоторые товары нет плана или "прошлого года" этом случае left (outer) join потеряет строки где есть план но с продажами у менеджеров не получилось.. т.е. кое-кто не понесёт ответственности за невыполнение "возложенных надежд" ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:51 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Rgmffn, Код: sql 1. 2. 3. 4. 5.
Выполнить и выложить сюда получившийся xml в виде файла с расширением sqlplan ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:51 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Rgmffn Проблема заключается в слишком долгом выполнении запросов: я join'ю к таблице Receipts таблицу Plan_sales по столбцам [date], [id_shop], [id_good], снова join'ю таблицу receipts для получения выручки [sale] за прошлый год, и при небольшом итоговом количестве строк (~5k) время выполнения доходит до 6-7 минут. Индексы по дате, а в запросе есть даты, в том числе в условиях джойнов? Вот оно и медленно. Зачем по дате индексы сделали, секционирование? :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 14:09 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
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 ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 14:13 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
invm, ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 14:13 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
alexeyvg, по дате необходим кластерный индекс, т.к. дата есть основной параметр для любых выборок из таблицы. Процедура на вход получает даты, все факты идут по дате. А самое главное, руководитель сказал "делать по дате!") Насколько я сейчас понимаю, в процессе выполнения этой задачи и должна (по "стажёрскому" сценарию) возникать такая проблема. Намёк заключался в том, что необходимо использовать UNION ALL. Единственное, что здесь в принципе возможно заюнионить, - это выборка нужных мне продаж по дате, нужных мне планов по дате, нужных мне продаж за прошлый год по дате, из двух таблиц с выполняющимся дважды запросом к одной из них. И как-то хитро провести юнион, чтобы в итоге это выглядело как результат join'a (или не как результат join'a? я сам с этим не разобрался и до сих пор не получается) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 14:16 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Rgmffn, 1. В плане совершенно другой запрос, а не тот, который было показан первоначально. 2. Из-за неверных оценок кардинальности получился кривой план. Поэтому, для начала, а) обновите статистику таблиц и б) добавьте к запросу option (recompile) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 15:54 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
invm Rgmffn, 1. В плане совершенно другой запрос, а не тот, который было показан первоначально. 2. Из-за неверных оценок кардинальности получился кривой план. Поэтому, для начала, а) обновите статистику таблиц и б) добавьте к запросу option (recompile) + неплохо бы избавиться от @storeTable, если там не одна (сотня) записей ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 16:06 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
Код: sql 1. 2. 3. 4. 5. 6. 7.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 16:35 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
aleks222, любопытно а в чем будет практическая польза? мне для расширения кругозора Код: sql 1. 2. 3. 4. 5. 6. 7.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 16:43 |
|
Оптимизация запроса - план/факт продаж
|
|||
---|---|---|---|
#18+
komrad, По s в текущем запросе и так идёт полное сканирование, поэтому проще посчитать скаляр s,date - 10000 и попытаться получить seek на spy, нежели отдать расчёт скаляра на этап извлечения данных из spy, где из-за этого расчёта скорее всего будет scan. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 17:08 |
|
|
start [/forum/topic.php?fid=46&msg=40015925&tid=1685440]: |
0ms |
get settings: |
8ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
60ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
others: | 292ms |
total: | 437ms |
0 / 0 |