(57 тысяч строк), delivery_speed_src2region ( 22310 строк), delivery_speed_src2pvz (2875829 строк)? Несмотря на то, что в этих таблицах есть индексы по джойненым полям. seq_page_cost=1, поднимал до 30
https://pastebin.com/krCVYGmw
EXPLAIN (analyze, buffers) нужен
analyze означает, что запрос выполнился. Если он выполнится, меня он больше не будет интересовать — это однорзовый запрос. После того, как он выполнится, я про него забуду) Выполняется часов пять, поэтому могу только estimated
Тогда покажите SELECT version(); , EXPLAIN (VERBOSE, SETTINGS) и \d+ каждой таблицы, хотя бы.
https://pastebin.com/EcMheLxm
Ответ: потому что это явно выгоднее с такими индексами — всё равно надо в таблицы идти за "вторым" полем, например (см. Output): -> Seq Scan on stage.branch_office bo (cost=0.00..1875.71 rows=57171 width=14) Output: bo.ctid, bo.office_id, bo.add_region_id А там есть только: "branch_office_pkey" PRIMARY KEY, btree (office_id)
а Seq Scan ON report.delivery_speed_src2region sd2 - из-за того, что в output есть sd2.speed? Если да, не дешевле ли в таком случае просто было бы взять значение speed из строки, найденной по входящим в индекс полям region_id и src_office_id ?
Да, из-за этого. По оценкам — нет, не дешевле (видимо, планировщик вычисляет, что всё равно понадобится большая часть значений из этой таблицы). Кстати, она всё равно крошечная, так что на практике о ней не стоит и думать.
тот же запрос. Таблица delivery_speed_src2pvz (2875829 строк). Output: sd.speed, sd.ctid, sd.src_office_id, sd.dst_office_id. Всё, кроме ctid добавил в индекс. Почему по ней всё ещё идёт Seq Scan, хотя она явно не малая — почти 3 млн? https://pastebin.com/CCXCmFuQ
Тут уже оценки вот этой части: SELECT f.srid, f.create_dt, sd.speed FROM facts.srid_last_state AS f JOIN report.delivery_speed_src2pvz AS sd ON f.src_office_id = sd.src_office_id AND f.dst_office_id = sd.dst_office_id WHERE f.create_dt < '2022-11-01'::timestamptz AND f.first_date_stat IS NULL; отдельно нужно смотреть (и, возможно, и подробнее — с set enable_* = off;) — тут может быть несколько причин.
Мне вот куда удивительнее, что он планирует зачем-то index scan на facts.srid_last_state Там что, реально настолько большэ строк, чем тут выдаётся? (По моим прикидкам — миллионов 500 должно быть, чтобы оно переключилось.)
Ну и да... Не знаю, поможэт ли это хоть как-то, но work_mem=128M на этом жэлезе для одного важного запроса выглядит странно.
facts.srid_last_state - 3,3 млрд строк
Тогда нельзя исключать, что он прав, да.
то есть, с точки зрения оптимизатора, делать последовательное сканирование таблицы такого размера — оправдано?
прошу прощения, неверно прочитал комментарий
Ну и да... Он думает, что тупо выборка srid по индэксу idx_srid_last_state__create_dt (create_dt < '2022-11-01 00:00:00+03'::TIMESTAMP WITH TIME zone) FILTER: (first_date_stat IS NULL) займёт треть этого времени. То есть пару часов. А обновление — втрое большэ, соответственно. Ну... Похожэ на правду, на самом деле. Но поставить 30 гиг work_mem я бы можэт и попробовал.
/offtopic весь CASE можно заменить на: f.create_dt + INTERVAL '1 HOUR' * COALESCE(sd.speed + 6, sd2.speed + 6, 84)
Это не оффтопик и совершэнно правильно — но топикстартеру вряд ли поможэт...
1. Если у вас есть время, то можно сделать индекс с фильтром WHERE (first_date_stat IS NULL) но судя по оценке (cost=0.58..106217414.34 ROWS=117158208 width=54) не поможет 2. UPDATE делать не сразу весь, а кусками (днями, месяцами), будет заметно быстрее
>2. UPDATE делать не сразу весь, а кусками (днями, месяцами), будет заметно быстрее Если 5 часов подвисшэго вакуума не являются проблемой — то приведёт это только к тому, что оно будет делаться днями, хе-хе.
Как будет время, покажите пожалуйста два плана: 1. UPDATE facts.srid_last_state f SET first_date_stat = f.create_dt + INTERVAL '1 HOUR' * COALESCE(sd.speed + 6, sd2.speed + 6, 84) FROM stage.branch_office bo INNER JOIN report.delivery_speed_src2pvz sd ON TRUE AND sd.src_office_id = f.src_office_id AND sd.dst_office_id = f.dst_office_id INNER JOIN report.delivery_speed_src2region sd2 ON TRUE AND sd2.region_id = bo.add_region_id AND sd2.src_office_id = f.src_office_id WHERE TRUE AND f.create_dt BETWEEN '2022-10-01'::timestamptz AND '2022-11-01'::timestamptz AND f.first_date_stat IS NULL AND bo.office_id = f.dst_office_id; ----------------------------- 2. UPDATE facts.srid_last_state f SET first_date_stat = f.create_dt + INTERVAL '1 HOUR' * COALESCE(sd.speed + 6, sd2.speed + 6, 84) FROM stage.branch_office bo INNER JOIN report.delivery_speed_src2pvz sd ON TRUE AND sd.src_office_id = f.src_office_id AND sd.dst_office_id = f.dst_office_id INNER JOIN report.delivery_speed_src2region sd2 ON TRUE AND sd2.region_id = bo.add_region_id AND sd2.src_office_id = f.src_office_id WHERE TRUE AND f.create_dt < '2022-11-01'::timestamptz AND f.first_date_stat IS NULL AND bo.office_id = f.dst_office_id;
Обсуждают сегодня