Я пытаюсь обновить таблицу из другой, запрос завершается успешно, но строки не обновляются. Каждая таблица содержит ~32 млн строк. Я использую PostgreSQL 11.12.
Вот 2 таблицы (я удалил столбцы, не используемые в запросе):
CREATE TABLE IF NOT EXISTS public.sirene_geo
(
siret character varying(50) NOT NULL,
x numeric,
y numeric,
CONSTRAINT sirene_geo_etablissement_pkey PRIMARY KEY (siret)
)
CREATE TABLE IF NOT EXISTS public.sirene_eta
(
siret character varying(50) NOT NULL,
latitude numeric,
longitude numeric,
CONSTRAINT sirene_stock_etablissement_pk PRIMARY KEY (siret)
)
Запрос на обновление:
UPDATE sirene_eta eta
SET longitude = x,
latitude = y
FROM sirene_geo geo
WHERE eta.siret = geo.siret
В pgAdmin (v5.4) для поля «Затронутые строки» указано -1.
Postgres использует стратегию хэш-соединения для завершения обновления.
Кроме того, в sirene_geo меньше строк, чем в sirene_eta, но Postgres строит хеш-таблицу на sirene_geo (что приводит к несовпадению некоторых строк).
Когда я пытаюсь выполнить обновление с ограничением внутри таблицы подзапросов, оно работает, но использует стратегию вложенного цикла, которая определенно не подходит для обновления всей таблицы.
Обновление:
Нет параллельной записи. Я проверил журнал, и действительно, есть ошибка:
ERROR: could not write to file "base/pgsql_tmp/pgsql_tmp9264.8256": No space left on device
Кроме того, если есть одновременная запись, вы можете легко столкнуться с взаимоблокировками при одновременном обновлении 32M строк в случайном порядке ... Есть ли?
Привет, приятно знать об опечатке, я отредактировал свой пост. В настоящее время я использую PgAdmin v5.4 и Postgres 11.12. Нет параллельной записи. Я проверил журнал, и действительно, есть ошибка: ERROR: could not write to file "base/pgsql_tmp/pgsql_tmp9264.8256": No space left on device
Пожалуйста, уточните через правки, а не комментарии. Пожалуйста, не добавляйте «EDIT», просто отредактируйте для наилучшего представления. Но не редактируйте таким образом, чтобы сделать разумные опубликованные ответы недействительными. Пожалуйста, удалите и пометьте устаревшие комментарии. PS А какой вопрос вы пытаетесь задать? ПС минимальный воспроизводимый пример
У вас заканчивается место на устройстве хранения. Освободить место на диске (или то, что вы используете в качестве хранилища) перед началом большого UPDATE
. Удалить ненужные файлы (не связанные с базой данных). Или как-то уменьшить базу данных.
Простой VACUUM
мощь выполняет свою работу. Или VACUUM FULL
(блокирует одновременный доступ), чтобы агрессивно сжимать физическое хранилище. Если вы не можете позволить себе блокировку, рассмотрите один из неблокирующих инструментов сообщества. Видеть:
VACUUM FULL
предпочтительно нет в sirene_eta
(целевой таблице), которая в любом случае будет повторно использовать мертвые кортежи в UPDATE
(после простого VACUUM
). И убедитесь, что VACUUM
не заблокирован длительной транзакцией. Видеть:
Что бы вы ни делали, если вы не ожидаете, что целевые строки все действительно изменятся, добавьте условие WHERE
для фильтрации пустых обновлений (за полную стоимость!)
UPDATE sirene_eta eta
SET longitude = geo.x
, latitude = geo.y
FROM sirene_geo geo
WHERE eta.siret = geo.siret
AND (eta.longitude IS DISTINCT FROM geo.x -- !
OR eta.latitude IS DISTINCT FROM geo.y)
Может даже решить вашу проблему, сократив объем работы (значительно). (Оказывается, это не в вашем случае.
Видеть:
Спасибо за совет, но, к сожалению, я хочу обновить все строки, чтобы это не изменило мою проблему.
Нет такого понятия, как «Постгре». wiki.postgresql.org/wiki/Identity_Guidelines Укажите свою версию Postgres и pgAdmin. Мой pgAdmin4 (текущая версия 6.7) сообщает стандартный тег команды «UPATE 0», когда ни одна строка не была затронута. Я подозреваю, что вы столкнулись с ошибкой. Время соединения вышло? Или из памяти? Вы должны увидеть правильное сообщение об ошибке! Проверьте логи вашей БД.