Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL alexeyvg, Алгоритм расчета такой,что однозначно нужно считать каждую неделю с учетом предыдущих данных. Вы говорите "нужно считать каждую неделю с учетом предыдущих данных", а в запросе вы делаете другое - считаете все следующие записи по текущей записи, потом считаете все следующие записи по следующей записи, и т.д. Это очень сильно отличается. "нужно считать каждую неделю с учетом предыдущих данных" в какой то степени похоже на "накопительный итог", это можно считать, не апдэйтя данные за всё время столько раз, сколько строк в таблице ,а за один проход. И, конечно, не апдэйтя таблицу, а вставляя в новую. Тогда у вас общее время пересчёта по сути будет равно одному скану таблицы (правда, будут затраты памяти, для хранения накопительных счётчиков, по числу сочетаний StoreID и GoodID) То есть в тыщи раз быстрее, чем сейчас. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 15:23 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
alexeyvg, alexeyvg, Запрос: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. В идеале вместо WHERE [snp].[dt] BETWEEN @dtnext AND @curperiodend нужно WHERE [snp].[dt] =@dtnext Т.е. брать данные одной недели и апдейтить их данными предыдущей. Но на предыдущей неделе может не быть данных по товару - они были 5/6/12... недель назад. Поэтому делается апдейт всего что после текущей (@dt), а как дойдет до недели где опять есть этот товар, то по нему проапдейтится сново все далее... Одним запросом это сделать - не могу сообразить как. Ведь данные по каждой неделе постоянно меняются и 10 неделя до начала расчета будет не той как после 2, 3 и тп шагов... По идее вот я получил данные по товару Х за 1 неделю и мне нужно не все со 2-й по 50-ю неделю обновлять, а только первую неделю где есть этот товар. Лишь в этом я вижу возможность уменьшить число строк для обновления. Т.е. нечто типа OUTER APPLY (SELECT TOP 1 ... ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 15:54 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Сделал так, чтобы наоборот для выбранной недели находились прошлые данные Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. Стало медленнее раза в 3. В добавок, OUTER APPLY при больших объемах у нас уже вызывал полное зависание (проц = 0%, диск = 0% и тп) при этом ошибок не давал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 16:46 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
автор OUTER APPLY (SELECT TOP 1 ...) да по куче, да с таким количеством предикатов... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 17:54 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL, OUTER APPLY ... order by откуда там взяться производительности. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 18:35 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL Одним запросом это сделать - не могу сообразить как. LAG (Price) OVER ( [ partition by StoreID, GoodID order by dt) вернёт вам значение Price для тех же StoreID и GoodID за предыдущий день ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 18:53 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL Стало медленнее раза в 3. В добавок, OUTER APPLY при больших объемах у нас уже вызывал полное зависание (проц = 0%, диск = 0% и тп) при этом ошибок не давал. Без индекса это неприемлемо (как и вариант с LAG) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 19:04 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL затраты по времени на построение индекса иногда съедают всю выгоду от них (не менее часа, думаю будет длится) Не для расчёта, а вообще, и не надо их строить-удалять ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.12.2020, 19:06 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
alexeyvg Oleg_SQL Стало медленнее раза в 3. В добавок, OUTER APPLY при больших объемах у нас уже вызывал полное зависание (проц = 0%, диск = 0% и тп) при этом ошибок не давал. Без индекса это неприемлемо (как и вариант с LAG) Я конечно не профессор, но кластерный индекс был построен по всем указанным полям. В данный момент я добавил при вставке во временную таблицу поле rn (row_number) и добавил его в кластерный индекс. Теперь добавил условие в INNER JOIN : AND snp.RN = snpPrev.RN + 1 Обработка взлетела )) Вот только много времени уходит на саму вставку в #salesPromo со всеми индексами и row_number(OVER(PARTITION BY... ORDER BY...). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 09:13 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
alexeyvg Oleg_SQL Одним запросом это сделать - не могу сообразить как. LAG (Price) OVER ( [ partition by StoreID, GoodID order by dt) вернёт вам значение Price для тех же StoreID и GoodID за предыдущий день Код: sql 1. 2. 3. 4. dt val lastvalue ----------- ----------- ----------- 20200101 100 NULL 20200108 NULL 100 20200115 NULL NULL 20200122 120 NULL а мне нужно для 20200122 значение lastvalue = 100. Последнее не пустое значение , а не значение прошлой строки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 11:26 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
alexeyvg Oleg_SQL затраты по времени на построение индекса иногда съедают всю выгоду от них (не менее часа, думаю будет длится) Не для расчёта, а вообще, и не надо их строить-удалять я же в расчете использую временную таблицу... как им там быть то? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 11:31 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL, вы индекс строите после заполнения таблицы или до? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 12:36 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
felix_ff Oleg_SQL, вы индекс строите после заполнения таблицы или до? Конечно же ДО ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 13:39 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL, В таком случае что там у вас с планом запроса наполнения временной таблицы? есть ли оператор сортировки? Для такого некислого объема вставка по определению может быть не особо быстрой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 13:47 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
felix_ff Oleg_SQL, В таком случае что там у вас с планом запроса наполнения временной таблицы? есть ли оператор сортировки? Для такого некислого объема вставка по определению может быть не особо быстрой. Со вставкой уже ничего не поделаешь - манипулировать с рабочей таблицей (индексы и тп) мне не дают. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 14:17 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL а мне нужно для 20200122 значение lastvalue = 100. Последнее не пустое значение , а не значение прошлой строки. Код: sql 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 15:09 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL alexeyvg пропущено... Индексы должны быть в базе. Не для расчёта, а вообще, и не надо их строить-удалять я же в расчете использую временную таблицу... как им там быть то? Другое дело, что схема исходных таблиц сложнее, и по ней не получится так легко сделать интересующий сложный запрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 15:12 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL, Вообще есть смысл строить все индексы уже после наполнения временной таблицы. Сначала кластерный, потом некластерные, если есть. Если вы построите индекс по существующим данным, вместе с индексом построится актуальная статистика. А если наоборот - останется только надеяться на автопересчет статистик. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 15:28 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
[quot alexeyvg#22246312] Oleg_SQL а мне нужно для 20200122 значение lastvalue = 100. Последнее не пустое значение , а не значение прошлой строки. Да, всё верно. Я уже заметил и поправил. На скорость это не повлияло. Но это был тестовый запрос для успокоения души )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 15:33 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
0wl Oleg_SQL, Вообще есть смысл строить все индексы уже после наполнения временной таблицы. Сначала кластерный, потом некластерные, если есть. Если вы построите индекс по существующим данным, вместе с индексом построится актуальная статистика. А если наоборот - останется только надеяться на автопересчет статистик. Записать 500 млн записей, а потом начать строить кластерный индекс? Это будет реально быстрее? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 15:39 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL Записать 500 млн записей, а потом начать строить кластерный индекс? Это будет реально быстрее? Я бы и рад сказать «да, я был прав» или «нет, я ошибся», но тут возможны варианты. Если сначала залить данные в кучу, а потом построить по ним индекс, они запишутся 2 раза. И нужно будет выделить место в файле данных для создания индекса. Зато можно использовать BULK INSERT (ну или SELECT … INTO) и ускорить первоначальную вставку в кучу. (см. https://docs.microsoft.com/en-US/sql/relational-databases/import-export/prerequisites-for-minimal-logging-in-bulk-import?view=sql-server-ver15#table-requirements-for-minimally-logging-bulk-import-operations) С другой стороны, если данные заливаются в кластерный индекс пачками, в несколько транзакций, то в процессе заливки несколько раз сработает автоапдейт статистик. Но это чтения, а не запись, к тому же, чтения какого-то сэмпла, а не всей таблицы. В общем, я бы замерил варианты. Ну и если выбирать второй вариант, то по окончании заливки пересчитал бы статистику с FULLSCAN, чтобы гарантировать, что план будет эффективным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 17:50 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
0wl Зато можно использовать BULK INSERT (ну или SELECT … INTO) и ускорить первоначальную вставку в кучу. Но надо одной операцией, а не "пачками". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 19:17 |
|
||
|
Большой UPDATE
|
|||
|---|---|---|---|
|
#18+
Oleg_SQL Да, всё верно. Я уже заметил и поправил. На скорость это не повлияло. Но это был тестовый запрос для успокоения души )) Oleg_SQL В идеале вместо WHERE [snp].[dt] BETWEEN @dtnext AND @curperiodend нужно WHERE [snp].[dt] =@dtnext Т.е. брать данные одной недели и апдейтить их данными предыдущей. Но на предыдущей неделе может не быть данных по товару - они были 5/6/12... недель назад. Поэтому делается апдейт всего что после текущей (@dt), а как дойдет до недели где опять есть этот товар, то по нему проапдейтится сново все далее... Как я понял, у вас отсутствие данных означает не наличие записи во значением поля Price, равным NULL, а именно отсутствие записи. Если "отсутствие данных" означает "отсутствие записи", то цикл апдэйтов заменяется на рекурсивный CTE по датам, с заменой OUTER APPLY на LAG, и на итоговую вставку в таблицу результата, соответственно, с возможностью использовать индексы постоянных таблиц Тогда всё будет кардинально быстрее. Ну или вообще нужно менять модель данных, на что выше намекали, но на это вы вряд ли пойдёте, это уже не "оптимизация", а "перепроектирование системы". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.12.2020, 19:28 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=40026739&tid=1685305]: |
0ms |
get settings: |
9ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
57ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
76ms |
get tp. blocked users: |
1ms |
| others: | 248ms |
| total: | 431ms |

| 0 / 0 |
