Оптимизация запроса в PostgreSQL - PullRequest
0 голосов
/ 01 ноября 2018
CREATE TABLE master.estado_movimiento_inventario
(
  id integer NOT NULL,
  eliminado boolean NOT NULL DEFAULT false,
  fundamentacion text NOT NULL,
  fecha timestamp without time zone NOT NULL,
  id_empresa integer NOT NULL,
  id_usuario integer NOT NULL,
  id_estado integer NOT NULL,
  id_movimiento integer NOT NULL,
  se_debio_tramitar_hace bigint DEFAULT 0,
  CONSTRAINT "PK15estadomovtec" PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE master.estado_movimiento_inventario
  OWNER TO postgres;

Эта таблица отслеживает состояние каждого движения инвентаря в моей бизнес-логике. Таким образом, каждое движение, которое еще не закончено (нет никакого id_estado = 3 или id_estado = 4 для любого id_movimiento в таблице master.estado_movimiento_inventario) должно хранить в поле se_debio_tramitar_hace своего последнего состояния разницу между now() и fecha поле каждый раз при выполнении запланированной задачи (Windows).

Запрос, который я построил для этого:

with update_time as(
   SELECT  distinct on(id_movimiento) id 
   from master.estado_movimiento_inventario 
   where id_movimiento not in (
      select id_movimiento 
      from master.estado_movimiento_inventario 
      where id_estado = 2 or id_estado=3
   ) order by id_movimiento, id desc
)
update master.estado_movimiento_inventario mi 
  set se_debio_tramitar_hace= EXTRACT(epoch FROM now()::timestamp - mi.fecha )/3600
  where mi.id in (select id from update_time);

Это работает, как и ожидалось, но я подозреваю, что это не оптимально, особенно в операции обновления, и вот мое самое большое сомнение: что оптимально при выполнении этой операции обновления:

  • Выполняйте обновления так же, как в настоящее время или
  • Эквивалент функции postgresql этому:

    foreach (update_time.id as row_id) { обновить master.estado_movimiento_inventario mi set diferencia = now () - mi.fecha где mi.id = row_id; }

Извините, если я не достаточно ясен, у меня нет большого опыта работы с базами данных, хотя я понял теорию позади, но не слишком много работал с ней.

Редактировать

Обратите внимание, что id_estado не уникален для id_movimiento, как показано на рисунке:

enter image description here

1 Ответ

0 голосов
/ 01 ноября 2018

Я думаю, что это улучшает CTE:

with update_time as (
      select id_movimiento, max(id) as max_id
      from master.estado_movimiento_inventario 
      group by id_movimiento
      having sum( (id_estado in (2, 3))::int ) = 0
     )
update master.estado_movimiento_inventario mi 
  set diferencia = now() - mi.fecha 
  where mi.id in (select id from update_time);

Если последним идентификатором будет тот, который находится в состоянии "2" или "3", я бы просто сделал:

update master.estado_movimiento_inventario mi 
    set diferencia = now() - mi.fecha 
    where mi.id = (select max(mi2.id)
                   from master.estado_movimiento_inventario mi 
                   where mi2.id_movimiento = mi.id_movimiento
                  ) and
          mi.id_estado not in (2, 3);
...