|
Postgresql 12.6. Как ускорить скрипт с update? Обновление 18 млн записей по юрлицам РФ | ☑ | ||
---|---|---|---|---|
0
GANR
14.10.23
✎
21:08
|
Postgresql 12.6, таблица svjul 18 млн. записей, 100Гб, 3 колонки id (число, ключ), enddate (дата), data (jsonb). Колонка data содержит поля OGRN и DataVip. По одному ОГРН возможно несколько записей. Нужно написать SQL-скрипт, который установит enddate = '2022-12-31' записям, у которых DataVip не максимальна для её ОГРН. Время отработки скрипта должно быть минимально.
На данный момент скрипт выглядит так - время неудовлетворительное create index if not exists idx_deduplicate_svjul_btree_ogrn on svjul using btree ((data ->> 'OGRN')); update svjul set enddate = '2023-10-05' where ( svjul.data ->> 'OGRN', svjul.data ->> 'DataVip' ) <> ( select distinct on (svjul1.data ->> 'OGRN') svjul1.data ->> 'OGRN', svjul1.data ->> 'DataVip' from svjul as svjul1 where svjul1.data ->> 'OGRN' = svjul.data ->> 'OGRN' order by svjul1.data ->> 'OGRN', svjul1.data ->> 'DataVip' desc ) ; Ваши предложения? |
|||
1
Волшебник
14.10.23
✎
21:13
|
Покажите EXPLAIN
|
|||
2
Волшебник
14.10.23
✎
21:14
|
Ещё нужны объём данных: количество записей и гигабайт, а также время: что значит "неудовлетворительное"?
|
|||
3
Волшебник
14.10.23
✎
21:15
|
Да, ещё надо понять частоту запуска этого скрипта. Зачем всё это?
|
|||
4
GANR
14.10.23
✎
21:16
|
"QUERY PLAN"
"Update on svjul (cost=0.00..114458012.59 rows=50028 width=132)" " -> Seq Scan on svjul (cost=0.00..114458012.59 rows=50028 width=132)" " Filter: (SubPlan 1)" " SubPlan 1" " -> Unique (cost=1142.64..1143.89 rows=500 width=64)" " -> Sort (cost=1142.64..1143.89 rows=500 width=64)" " Sort Key: ((svjul1.data ->> 'DataVip'::text)) DESC" " -> Bitmap Heap Scan on svjul svjul1 (cost=12.29..1120.23 rows=500 width=64)" " Recheck Cond: ((data ->> 'OGRN'::text) = (svjul.data ->> 'OGRN'::text))" " -> Bitmap Index Scan on idx_deduplicate_svjul_btree_ogrn (cost=0.00..12.17 rows=500 width=0)" " Index Cond: ((data ->> 'OGRN'::text) = (svjul.data ->> 'OGRN'::text))" |
|||
5
Волшебник
14.10.23
✎
21:16
|
Что такое svjul ?
|
|||
6
GANR
14.10.23
✎
21:17
|
(3) Вроде как индекс-то срабатывает, вот только приходится искать дубли 18 млн. раз. Неужто ситуация патовая
|
|||
7
GANR
14.10.23
✎
21:18
|
(5) это таблица юридических лиц РФ в топике написал техническую составляющую
|
|||
8
Волшебник
14.10.23
✎
21:18
|
(6) При "Update" индексы десятое дело, они только тормозят обычно. Хотя в Вашем случае 18 млн строк для обновления — это нонсенс. Зачем столько обновлять?
|
|||
9
Волшебник
14.10.23
✎
21:19
|
(7) Вы глупости делаете.
|
|||
10
Волшебник
14.10.23
✎
21:20
|
Обновляйте только своих контрагентов, не трогайте остальные 18 млн юрлиц РФ
|
|||
11
H A D G E H O G s
14.10.23
✎
21:20
|
Вытащить дату в отдельное поле и не аться с этими json
|
|||
12
Волшебник
14.10.23
✎
21:22
|
(11) Придётся обновлять отдельное поле.
|
|||
13
GANR
14.10.23
✎
21:22
|
(8) На урезанной таблице из 100000 строк индексы помогли. Поиск без них 100% будет по полчаса для каждой из 18 млн. записей работать.
Зачем? Чтобы оставить незакрытыми только самые актуальные согласно дате выписки записи. (9) Ваши предложения? |
|||
14
H A D G E H O G s
14.10.23
✎
21:22
|
(0) А вот скажите - какой большой смысл хранить в json/xml? Еще и индексировать его поля. Чтобы что, быстрее его выплевывать по запросу?
|
|||
15
GANR
14.10.23
✎
21:23
|
(14) Это отдельная история и длинная. Не в этой ветке. Но так надо.
|
|||
16
Волшебник
14.10.23
✎
21:24
|
(15) Вам надо ворочать 18 млн записей, Вы и трахайтесь.
|
|||
17
H A D G E H O G s
14.10.23
✎
21:24
|
(12) это быстро. Относительно.
|
|||
18
GANR
14.10.23
✎
21:25
|
(10) Надо именно всю базу.
|
|||
19
H A D G E H O G s
14.10.23
✎
21:26
|
(15) заведи отдельные поля или общий хэш поиска, заполни их из json, добавь автозаполнение в призаписи() и убери индексы json
|
|||
20
Волшебник
14.10.23
✎
21:30
|
(19) Это всё не поможет. Он обновляет данные каждый день по всем 18 млн записям.
|
|||
21
GANR
14.10.23
✎
21:34
|
(20) Слава богу НЕ каждый день. Разовая операция. Потом данные подливаем в БД по дню с ЕГРЮЛ. Только новые дедуплицировать
|
|||
22
GANR
14.10.23
✎
21:35
|
Уже потом
|
|||
23
Волшебник
14.10.23
✎
21:39
|
У вас там дурдом
|
|||
24
GANR
14.10.23
✎
21:43
|
(23) У нас тут МДМ - система, которая хранит и раздает по АПИ справочники РФ. ЕГРЮЛ самый проблемный. Скажите ещё спасибо, что нераспаковывающиеся архивы и битые ХМЛ перестали присылать.
|
|||
25
Волшебник
14.10.23
✎
21:44
|
(24) Спасибо.
|
|||
26
H A D G E H O G s
14.10.23
✎
21:54
|
(24) Java?
|
|||
27
GANR
14.10.23
✎
22:16
|
(26) Kotlin
|
|||
28
АНДР
14.10.23
✎
22:20
|
В России 3+М ЮЛ и примерно столько же ИП. Предлагаю сначала создать вспомогательную таблицу с полями OGRN и DataVip. Далее по обстоятельствам, по крайней мере вместо двух сканов таблицы при апдейте будет один.
|
|||
29
GANR
14.10.23
✎
22:23
|
(28) А вот это кстати может сработать, временная таблица, с 2-мя полями весит уже не 100Гб, а где-то 500 Мб, что вполне влезет в ОЗУ. Если ещё проиндексировать поиск может значительно ускориться. Спасибо.
|
|||
30
АНДР
14.10.23
✎
22:57
|
(29) тогда делай сначала с полями id, enddate, ogrn, datavip. Из нее ещё одну с ogrn, max(datavip). Апдейть первую через join по огрн с условием на даты, потом аналогично исходную через join по id с условием на дату.
|
|||
31
АНДР
14.10.23
✎
23:00
|
Индексировать можно первую по id для второго join. Больше индексов не надо.
|
|||
32
GANR
14.10.23
✎
23:10
|
(30) Да, кстати ловчее всего будет в ВТ вытащить ИД-шники незакрываемых записей, а потом
update svjul set enddate='2022-12-31' where not exists (select id from wtsvjul where wtsvjul.id = svjul.id) Где wtsvjul - временная таблица. |
|||
33
АНДР
14.10.23
✎
23:44
|
(32) условия, отличные от "=" для множеств при апдейде плохо!
У тебя и в (0), и в (32) при апдейте используются операции с множествами в условии. + (30) Прочитай про секцию From тут https://postgrespro.ru/docs/postgresql/9.6/sql-update |
|||
34
GANR
15.10.23
✎
06:51
|
(33) Я так и так попробую на урезанной таблице. Из каждого правила, я скажу, есть исключения. С JOIN как показывает практика далеко не так всё хорошо в Postgres и индекс с ним не всегда цепляется.
|
|||
35
GANR
15.10.23
✎
06:56
|
Ясно одно - проверки КАЖДОЙ из 18 миллионов записей никак не избежать. Вопрос лишь в том как её ускорить.
|
|||
36
GANR
15.10.23
✎
07:01
|
А мне ещё одна идея пришла. Проставить всем записям 2022-12-31, а потом только для тех что с нужными ID-шниками открыть. Вот это должно быть максимально шустро.
|
|||
37
АНДР
15.10.23
✎
07:59
|
(35) В (0) каждый json разбирается дважды, да ещё для каждой строки идёт сравнение на неравенство с каждой столкой массива "актуальных данных (её и нужно индексировать)".
Я тебе предлагаю разобрать json'ы только 1 раз и вне транзакции апдейта. Нюансы каждого шага зависят как от конкретного набора данных, так и от сервера. Тут я не подскажу. |
|||
38
АНДР
15.10.23
✎
08:03
|
(35) уверен, что затык в процессоре а не дисках? Хоть и будет две транзакции апдейта, но они у тебя будут идти последовательно и количество апдейтов будет существенно выше. Выйгрыш времени крайне сомнителен
|
|||
39
Гена
15.10.23
✎
08:32
|
(0) А данные получаете с сайта налог.ру? Просто если не жадничать и получать эти данные легально за плату, то там уже есть готовые файлы xml по ЕГРЮЛ как для полной базы на определённую дату, так и отдельные к ней обновления на каждый последующий день.
Если же сами написали приблуду по массовому скачиванию бесплатно по каждому отдельному ЕГРЮЛ, то это ловится. Если же скачиваете с левого сайта, который уже вытащил базу и выложил её в открытый доступ, то не факт, что там данные свежие. |
|||
40
GANR
15.10.23
✎
09:37
|
(38) Естественно в дисках проблема. Хранись хотя-бы правая часть условия отбора в ОЗУ в индексированном виде и используй его запрос по уму, таких тормозов бы не было. Даже плохенькое ОЗУ в сто раз быстрее любого жесткого диска.
(39) Да, выкачиваем зипованные ХМЛ-ки с официального источника ФНС. Затем загоняем в таблицу БД эти данные предварительно преобразовав эти данные в JSON. Ну а потом различными способами используем эти данные раздаем по REST и JMS. |
|||
41
GANR
15.10.23
✎
09:46
|
Возможно, использование RAM-диска для временных таблиц и их индексов облегчит жизнь. Но это надо настраивать.
|
|||
42
Гена
15.10.23
✎
10:32
|
(40) Ну коль установили клиентам базу по ЕГРЮЛ на какую-то дату (20 млн) и есть обновления строк на сто, то почему просто не подгружать обновления?
Коллеги, что-то тут нечисто ) Something is rotten in the state of Denmark... |
|||
43
GANR
15.10.23
✎
11:02
|
(42) Просто есть уже нагруженная таблица с дублями. Ну и чтоб не перегружать заново решили попробовать её дедуплицировать. Я предлагал перегрузить, но это долго. Вот и решали иной выход искать.
|
|||
44
H A D G E H O G s
15.10.23
✎
11:44
|
И конкурсы интересные.
|
|||
45
GANR
15.10.23
✎
12:18
|
(44) Очень. В рамках 1С у меня возникал вопрос где мне могут потребоваться навыки 1С:Эксперт. Так вот за пределеами 1С возникает другой вопрос - где это может НЕ потребоваться.
|
|||
46
АНДР
15.10.23
✎
20:11
|
(40) Создавай промежуточную таблицу с полями Id, enddate и порциями апдейть svjul.
|
|||
47
АНДР
15.10.23
✎
20:12
|
(46) физическую
|
|||
48
GANR
16.10.23
✎
09:35
|
(46) Эффекта по сравнению с вложенным запросом практически нет - проверял.
create index if not exists idx_deduplicate_svjul_btree_anyfields on svjulv1 using btree ( (right(data ->> 'OGRN', 4)::integer), (data ->> 'OGRN'), (data -> 'SvUchetNO' ->> 'DataPostUch') desc, (data ->> 'DataVip') desc, id desc ); drop procedure if exists svjulv1_deduplicate; create or replace procedure svjulv1_deduplicate(closedate date) as $$ begin for i in 0..9999 loop if exists( select 1 from svjulv1 where right(data ->> 'OGRN', 4)::integer = i and enddate = closedate ) then raise info 'success early %', i; continue; end if; update svjulv1 set enddate = closedate where right(svjulv1.data ->> 'OGRN', 4)::integer = i and svjulv1.id not in ( select distinct on (right(svjulv11.data ->> 'OGRN', 4)::integer, svjulv11.data ->> 'OGRN') svjulv11.id from svjulv1 as svjulv11 where right(svjulv11.data ->> 'OGRN', 4)::integer = i order by right(svjulv11.data ->> 'OGRN', 4)::integer, svjulv11.data ->> 'OGRN', svjulv11.data -> 'SvUchetNO' ->> 'DataPostUch' desc, svjulv11.data ->> 'DataVip' desc, svjulv11.id desc ); commit; raise info 'success now %', i; end loop; end; $$ language plpgsql; call svjulv1_deduplicate('2022-12-31'); Я пробовал в update вложенный подзапрос из where на временную таблицу переделать - что так, что так время одинаковое. Кстати update ниже у меня отрабатывал мухой. Но на формирование временной таблицы все равно уходило то же время, что и на вложенный запрос в where. В итоге получил ту же минуту на обработку порции ОГРН по right(data ->> 'OGRN', 4)::integer update svjulv1 set enddate = closedate where id not in (select id from tempsvjul) |
|||
49
GANR
16.10.23
✎
09:37
|
+(47) Да, я про DataPostUch в 0 не сказал, дабы упростить задачу. Но в принципе его наличие/отсутствие не особо меняет дело
|
|||
50
GANR
16.10.23
✎
09:44
|
Короче говоря вот этот кусок самый тормозной
select distinct on (right(svjulv11.data ->> 'OGRN', 4)::integer, svjulv11.data ->> 'OGRN') svjulv11.id from svjulv1 as svjulv11 where right(svjulv11.data ->> 'OGRN', 4)::integer = i order by right(svjulv11.data ->> 'OGRN', 4)::integer, svjulv11.data ->> 'OGRN', svjulv11.data -> 'SvUchetNO' ->> 'DataPostUch' desc, svjulv11.data ->> 'DataVip' desc, svjulv11.id desc |
|||
51
GANR
16.10.23
✎
09:48
|
(50) возможно, если покрутить параметры планировщика, удастся ускорить
|
|||
52
DrZombi
16.10.23
✎
09:56
|
(15) Когда говорят "Так надо", смирись со временем выполнения, первое "Так надо", задает тон всему :)
|
|||
53
GANR
16.10.23
✎
10:18
|
(52) Да ты умеешь обрадовать)
|
|||
54
АНДР
16.10.23
✎
11:33
|
(50) А зачем бить по 4 последним знакам ОГРН!?
|
|||
55
GANR
16.10.23
✎
11:35
|
(54) это чтобы на 10000 транзакций разбить все множество обрабатываемых объектов
|
|||
56
АНДР
16.10.23
✎
11:38
|
(48) Временная таблица нужна что бы в JSON второй раз за ОГРН не лазить.
|
|||
57
АНДР
16.10.23
✎
11:38
|
(55) Бей по интервалам ID
|
|||
58
Garykom
16.10.23
✎
11:56
|
Задача прекрасно распараллеливается
Кто мешает запустить в нужное число потоков? А еще в PGSQL есть кластеризация с репликацией - это если потоков на одном сервере маловато будет |
|||
59
GANR
16.10.23
✎
12:25
|
(57) Не пойдет - надо в группе из ОГРН выбирать
|
|||
60
АНДР
16.10.23
✎
14:18
|
(59) Зачем? В (0) ты в JSON лазил для каждой строки дважды, а в (50) уже 10000 раз при проверке условия отбора в транзакцию и 10001 при апдейте.
|
|||
61
H A D G E H O G s
16.10.23
✎
17:23
|
||||
62
АНДР
16.10.23
✎
17:40
|
(61) Не, так не интересно. Мы тут за академический интерес к Postgre.
|
|||
63
GANR
16.10.23
✎
18:14
|
(61) (62) Индекс по полям jsonb почему-то медленно сканируется. А вот индекс по колонкам шустрее. По ходу придется мне ход конем делать - сделать колонки с ОГРН и датой выписки, заполнить их через update перебирая порционно по 10000 все id. И только потом применять что-то наподобие (61).
|
|||
64
GANR
16.10.23
✎
18:17
|
Jsonb по ходу довольно серьезно замедляет все.
|
|||
65
H A D G E H O G s
16.10.23
✎
18:21
|
(63)
заполнить их через update перебирая порционно по 10000 все id MS SQL сделает это за одну минуту. Максимум. Одной порцией. |
|||
66
H A D G E H O G s
16.10.23
✎
18:21
|
(63) см (11)
|
|||
67
H A D G E H O G s
16.10.23
✎
18:23
|
(63) В (61) только один кластерный индекс по id. Другие индексы не нужны, если у нас затронуто 12 млн строк из 18 млн. Какие нафиг тут индексы?
|
|||
68
H A D G E H O G s
16.10.23
✎
18:25
|
(65) Хотя нет, я не в курсе, как быстро mssql извлечет данные из json.
|
|||
69
GANR
16.10.23
✎
18:59
|
(68) Тут беда не только в количестве записей, они ещё и очень жирные 10-30 килобайт каждая и идут в jsonb. Даже простейший update svjul set code = data ->> 'OGRN' будет целый день работать. Ну а если данные в колонки перетащить то всё бодрее становится значительно.
|
|||
70
GANR
16.10.23
✎
19:01
|
Это плата за отсутствие возни по раскладке сотен атрибутов егрюла в отдельные колонки.
|
|||
71
H A D G E H O G s
16.10.23
✎
19:08
|
(69) Обычно все это бинарное хранится отдельно от данные таблицы, в специально обученных страницах данных. Поэтому обновление твоей таблицы будет быстрым и незаметным.
|
|||
72
H A D G E H O G s
16.10.23
✎
19:09
|
(70) Это понятно, я уже писал выше предположение.
|
|||
73
GANR
16.10.23
✎
19:10
|
(71) [быстрым и незаметным] увы, практика показывает обратное
|
|||
74
GANR
16.10.23
✎
19:12
|
(72) Я вот не пойму на кой хрен постгрес лазиет по этим бинарникам,если вся нужная инфа для выборки есть в индексе
|
|||
75
АНДР
16.10.23
✎
19:13
|
(73) Забудь про ОГРН при апдейте! В (48) ты уже заметил скорость обновления по id.
|
|||
76
АНДР
16.10.23
✎
19:15
|
(74) В индексе ему нужны все поля в приемлемом виде, а ты везде в апдейтах ему ОГРН из JSON'а суешь в условие.
|
|||
77
GANR
16.10.23
✎
19:29
|
(75) Так ведь его придется хоть в колонку то вынуть. Пока он в jsonb работать невозможно. Потом уже норм будет по крайней мере в селекте.
|
|||
78
Волшебник
модератор
16.10.23
✎
19:35
|
(0) Автор, у Вас низкая самооценка и высокая ответственность. Не торопитесь принимать решения и не психуйте.
Возьмите паузу. |
|||
79
АНДР
16.10.23
✎
19:36
|
См. Выше, лень искать. Его и дату надо один раз дёрнуть из json.
|
|||
80
H A D G E H O G s
16.10.23
✎
19:39
|
(74) (73) Все, о чем я пишу - относится к MS SQL. Возможно в Postgree по другому.
|
|||
81
H A D G E H O G s
16.10.23
✎
19:39
|
Но общие принципы должны же соблюдаться.
|
|||
82
GANR
16.10.23
✎
20:00
|
(78) Благодарю за внимание. Всё под контролем, не переживайте.
(79) Это сейчас и делается скриптом. К утру вынесение данных из jsonb в колонки закончится. А на сегодня всё. |
|||
83
Chai Nic
16.10.23
✎
20:04
|
Как я слышал, постгрес внутре версионник, а для любых версионников update в разы более тяжелая операция, чем delete+insert.
|
|||
84
Волшебник
16.10.23
✎
20:05
|
Ветка в топе
|
|||
85
ansh15
16.10.23
✎
20:34
|
Немного академического интереса https://habr.com/ru/companies/oleg-bunin/articles/597187/ и https://habr.com/ru/companies/oleg-bunin/articles/646987/
Потом автор не реагирует на распараллеливание, хотя и в предыдущей его ветке как ускорить запрос и в этой ему об этом говорили. |
|||
86
GANR
16.10.23
✎
21:30
|
(85) к распараллеливанию скептично отношусь, ибо записывающая/читающая головка диска одна
|
|||
87
H A D G E H O G s
16.10.23
✎
21:34
|
(85) Какая то наркомания.
|
|||
88
H A D G E H O G s
16.10.23
✎
21:36
|
(86) Головка диска там не причем. Диск тебе прочитает под 300 Гб в сек. нужных данных. Причем именно нужных.
А потом поделка Postgree будет строить цепочки toast, и разжимать их. Операция неконкурентная, блокировок быть не должно, паралельность должна быть. |
|||
89
GANR
16.10.23
✎
21:45
|
(85) (88) Хотите сказать, распараллеливание реально может в разы ускорить? Я просто не пробовал. А вы?
|
|||
90
Волшебник
16.10.23
✎
22:09
|
(86) Головка одна, но она пролетает много раз над одной дорожкой. Просто оставьте это дискам, а сами задайте нагрузку и смотрите.
|
|||
91
АНДР
16.10.23
✎
22:18
|
(88) только извлечённые данные нужно куда-то складывать для дальнейшей обработки и (86) не забывать про поддержку транзакционной целостности.
|
|||
92
ansh15
17.10.23
✎
01:56
|
(86) Умеренному скептицизму всегда может найтись место https://postgrespro.ru/docs/postgresql/15/when-can-parallel-query-be-used
Но попробовать же можно. Пример из статьи https://habr.com/ru/articles/305662/ воспроизводится хорошо(с чего бы было плохо?). Кстати, редакция СУБД(12.6) давно устарела. Там же все непрерывно меняется, улучшается и совершенствуется. |
|||
93
ansh15
17.10.23
✎
02:55
|
Вот select distinct исследовали https://www.percona.com/blog/introducing-postgresql-15-working-with-distinct/
В PG15 гораздо лучше выглядит, даже parallel distinct может быть. |
|||
94
ansh15
17.10.23
✎
03:03
|
Неясна суть программно-аппаратного окружения, в котором это все пытаются ускорить. Настройки СУБД, лежит ли вся база в shared buffers, и прочее потребление ресурсов памяти.
Как-то слишком трогательно смотрится забота о всего одной головке диска.. |
|||
95
Valdis2007
17.10.23
✎
07:03
|
(77) Пока он в jsonb работать невозможно...ага, а на операциях а на реляц.операциях с полями, jsonb работает еще и меделеннее чем json
|
|||
96
GANR
17.10.23
✎
07:06
|
(93) Если distinct начнет херовничать я просто заменю его на курсор, который будет перебирать упорядоченный результат запроса и каждый раз когда ОГРН будет отличаться от предыдущего складывать id в специальную таблицу.
К сожалению пока что нам не дадут 15 поставить по той простой причине, что на нем ПО не тестировалось. |
|||
97
АНДР
17.10.23
✎
08:13
|
(96) чем тебе не угодил max() group by?
|
|||
98
GANR
17.10.23
✎
08:25
|
(97) ну на самом деле полей несколько и не так с этим просто... хотя возможно
|
|||
99
GANR
17.10.23
✎
10:43
|
А можно ли в postgresql каким-то образом передавать функции в качестве параметров других функций без преобразования вызова в строки?
|
|||
100
Valdis2007
17.10.23
✎
12:23
|
(99) используй PL/Python
|
|||
101
GANR
17.10.23
✎
18:00
|
В итоге удалось мне добиться заполнения поля enddate за 2 часа. Скрипт из 0 работал бы неделю минимум. Скрипт теперь вот такой.
-- 0 minute drop table if exists tempsvjulv11; create table tempsvjulv11 (id bigint not null, code text not null, datapostuch text, datavip text, constraint tempsvjulv11_pkey primary key (id)); -- 1 hour 55 minute insert into tempsvjulv11(id, code, datapostuch, datavip) select id, data->>'OGRN', data -> 'SvUchetNO' ->> 'DataPostUch', data ->> 'DataVip' from svjulv1; -- 1 minute create index idx_deduplicate_tempsvjulv11_btreev1_codedpostdvipid on tempsvjulv11 using btree (code, datapostuch desc, datavip desc, id desc); -- 0 minute drop table if exists tempsvjulv2; create table tempsvjulv2(id bigint not null, constraint tempsvjulv12_pkey primary key (id)); -- 2 minute insert into tempsvjulv12(id) select distinct on (code) id from tempsvjulv11 order by code, datapostuch desc, datavip desc, id desc; -- 0 minute -- Не могу понять то ли эта махинация 4 строчек кода ниже -- то ли дроп всех индексов сокращают последующий update с 24 часов до 4 минут alter table if exists svjulv1 drop column code; alter table if exists svjulv1 drop column enddate; alter table if exists svjulv1 add column code text not null default '???'; alter table if exists svjulv1 add column enddate date; -- 4 minute update svjulv1 set code = (select coalesce(tempsvjulv11.code, '???') from tempsvjulv11 where tempsvjulv11.id = svjulv1.id), enddate = case when exists(select 1 from tempsvjulv12 where tempsvjulv12.id = svjulv1.id) then null else '2022-12-31'::date end; -- 0 minute drop table if exists tempsvjulv11; drop table if exists tempsvjulv12; drop procedure if exists svjulv1_setogrnenddate; АНДР ansh15 H A D G E H O G s Спасибо огромное, что так тщательно пытались разобраться! Интересное было исследование. Волшебник Тебе отдельное спасибо! Жалко, что у ветки нет отношения к 1С, но вцелом считаю, подобному место в книге знаний ну или хотя-бы в списке интересных веток каком-нибудь. |
|||
102
Волшебник
17.10.23
✎
21:11
|
(101) дроп всех индексов сокращают последующий update
|
|||
103
H A D G E H O G s
17.10.23
✎
21:18
|
(102) Не всегда. Чтобы делать update - надо искать записи, которые обновляются.
|
|||
104
GANR
17.10.23
✎
22:05
|
(103) Именно чтобы не было надобности индексы на целевой таблице держать я вынес нужные данные в облегченные вспомогательные таблички.
(102) Проведу ещё опыт с индексами и без, чтобы точно установить что же влияет - пересоздание колонок или всё же индекс. |
|||
105
Волшебник
17.10.23
✎
22:08
|
(103) Согласен. Но если UPDATE массовый и поиск чисто по ID, то дальше индексы только тормозят запись.
Кстати, я в базе мисты тоже на такое натыкался. Мне нужно было сделать UPDATE большой таблицы, но там были лишние индексы и обновление зависало. Я удалил индексы и UPDATE прошёл за вменяемое время. |
|||
106
GANR
17.10.23
✎
22:09
|
(105) У мисты база на Postgres?
|
|||
107
Волшебник
17.10.23
✎
22:15
|
(106) У нас MariaDB (бывший MySQL). Но это общие принципы для всех СУБД и всех баз.
|
|||
108
GANR
18.10.23
✎
00:07
|
(105) Попробовал на полной копии таблицы без индексов скрипт ниже. Сработало менее чем за один час без всяких пересозданий колонок.
-- 0 minute drop table if exists tempsvjul1; create table tempsvjul1 (id bigint not null, code text not null, datapostuch text, datavip text, constraint tempsvjul1_pkey primary key (id)); -- 30 minute insert into tempsvjul1(id, code, datapostuch, datavip) select id, data->>'OGRN', data -> 'SvUchetNO' ->> 'DataPostUch', data ->> 'DataVip' from svjul; -- 1 minute create index idx_deduplicate_tempsvjul1_btree_codedpostdvipid on tempsvjul1 using btree (code, datapostuch desc, datavip desc, id desc); -- 0 minute drop table if exists tempsvjul2; create table tempsvjul2(id bigint not null, constraint tempsvjul2_pkey primary key (id)); -- 2 minute insert into tempsvjul2(id) select distinct on (code) id from tempsvjul1 order by code, datapostuch desc, datavip desc, id desc; -- 4 minute update svjul set code = coalesce((select tempsvjul1.code from tempsvjul1 where tempsvjul1.id = svjul.id), '???'), enddate = case when exists(select 1 from tempsvjul2 where tempsvjul2.id = svjul.id) then null else '2023-10-05'::date end; -- 0 minute drop table tempsvjul1; drop table tempsvjul2; Волшебник вы правы. (103) Не могу представить ситуацию, при которой нельзя заменить индексы таблицы, к которой применяется update обращениями к вспомогательным таблицам. Можете привести пример? |
|||
109
GANR
18.10.23
✎
01:01
|
(107) А вы случайно не используете микросервисную архитектуру или бессерверное приложение? Я реально удивляюсь насколько шустро форум работает.
|
|||
110
GANR
18.10.23
✎
13:22
|
(105) Теперь решил обнулить code, enddate, построить индексы и повторить update для интереса - update, работавший без индексов 3-4 минуты теперь висит больше 2 часов. За это время индексы успевали построиться и ANALYZE пересчитать задранную статистику по всем полям до 1000.
|
|||
111
Волшебник
18.10.23
✎
13:25
|
(109) Нет, микросервисов не держим-с...
У нас мощное железо (нагрузка 1%) и новый очень быстрый движок (PHP 8.2 со своим встроенным кэшированием) + кэширование тела ветки (зелёную галочку вверху видели? это оно). |
|||
112
GANR
18.10.23
✎
14:30
|
(111) [У нас мощное железо] ну от запросов к большим таблицам с отбором/сортировкой по неиндексированным полям, я скажу, никакое железо не спасет. 200 Гб ОЗУ улетят только в путь.
|
|||
113
Волшебник
18.10.23
✎
14:31
|
(112) Всё верно. Для каждого запроса нужен анализ того, как он будет выполняться, как часто, какие ресурсы задействует.
|
|||
114
vis
18.10.23
✎
15:04
|
(111) > зелёную галочку вверху видели? это оно).
Не видно, а где она? |
|||
115
Волшебник
18.10.23
✎
15:13
|
(114) Вам лучше спросить здесь OFF: Обсуждение нового движка форума
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |