У меня есть представление, которое вычисляет некоторые поля. Я хотел обновить данные из этого представления (привязка модели к веб-платформе). У меня были проблемы, потому что вычисляемые поля не являются настоящими столбцами. Затем я создал функцию триггера, которая обрабатывает это.
Я провел тест «обновление из события» и «обновление из просмотра событий». Похоже, что функция, запускаемая обновлением, работает намного медленнее, чем «нормальное» обновление событий. Вот результат теста для 1000 создания / обновления событий:
# This report shows the user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time. The unit of time is seconds.
>> CREATE
user system total real
EVENT 3.268527 0.248713 3.517240 ( 5.777483)
VIEW 3.423386 0.232107 3.655493 ( 5.977695)
>> UPDATE
user system total real
EVENT 2.491350 0.227937 2.719287 ( 4.586648)
VIEW 2.861838 0.199566 3.061404 ( 6.240148)
=> nil
CREATE TABLE
инструкция:
CREATE TABLE public.events (
id bigint NOT NULL,
uuid uuid DEFAULT public.gen_random_uuid() NOT NULL,
establishment_id bigint,
name character varying NOT NULL,
start_at timestamp without time zone NOT NULL,
end_at timestamp without time zone NOT NULL,
canceled boolean DEFAULT false NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
published boolean DEFAULT false
);
EXPLAIN (ANALYZE, BUFFERS)
# EXPLAIN (ANALYZE, BUFFERS) UPDATE events SET name='some name', updated_at='2020-05-07 10:05:07.769711' WHERE events.id = 16212
Update on events (cost=0.29..8.38 rows=1 width=156) (actual time=0.187..0.194 rows=0 loops=1)
Buffers: shared hit=17 dirtied=2
-> Index Scan using events_pkey on events (cost=0.29..8.38 rows=1 width=156) (actual time=0.081..0.100 rows=1 loops=1)
Index Cond: (id = 16212)
Buffers: shared hit=7 dirtied=2
Planning Time: 7.301 ms
Execution Time: 1.127 ms
# EXPLAIN (ANALYZE, BUFFERS) UPDATE invitations_event_view SET name='some name', updated_at='2020-05-07 10:05:07.769711' WHERE invitations_event_view.id = 16212
Update on invitations_event_view invitations_event_view_1 (cost=4.73..26.41 rows=1 width=1164) (actual time=1.800..1.810 rows=0 loops=1)
Buffers: shared hit=15 dirtied=1
-> Subquery Scan on invitations_event_view (cost=4.73..26.41 rows=1 width=1164) (actual time=0.418..0.455 rows=1 loops=1)
Buffers: shared hit=4 dirtied=1
-> GroupAggregate (cost=4.73..26.40 rows=1 width=369) (actual time=0.353..0.371 rows=1 loops=1)
Group Key: e.id
Buffers: shared hit=4 dirtied=1
-> Nested Loop Left Join (cost=4.73..26.21 rows=1 width=157) (actual time=0.251..0.307 rows=1 loops=1)
Buffers: shared hit=4 dirtied=1
-> Nested Loop Left Join (cost=4.45..17.91 rows=1 width=161) (actual time=0.106..0.144 rows=1 loops=1)
Join Filter: (i.event_id = e.id)
Buffers: shared hit=4 dirtied=1
-> Index Scan using events_pkey on events e (cost=0.29..8.38 rows=1 width=141) (actual time=0.030..0.049 rows=1 loops=1)
Index Cond: (id = 16212)
Buffers: shared hit=3 dirtied=1
-> Bitmap Heap Scan on invitations i (cost=4.16..9.50 rows=2 width=28) (actual time=0.041..0.050 rows=0 loops=1)
Recheck Cond: (event_id = 16212)
Buffers: shared hit=1
-> Bitmap Index Scan on index_invitations_on_event_id (cost=0.00..4.16 rows=2 width=0) (actual time=0.021..0.030 rows=0 loops=1)
Index Cond: (event_id = 16212)
Buffers: shared hit=1
-> Index Scan using guests_pkey on guests g (cost=0.28..8.30 rows=1 width=12) (actual time=0.017..0.026 rows=0 loops=1)
Index Cond: (i.guest_id = id)
Planning Time: 3.420 ms
Trigger invitations_event_view_on_update_trigger: time=1.254 calls=1
Execution Time: 2.425 ms
Вот Вот функция:
CREATE OR REPLACE FUNCTION invitations_event_view_on_update() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
UPDATE events
SET establishment_id = NEW.establishment_id,
name = NEW.name,
start_at = NEW.start_at,
end_at = NEW.end_at,
canceled = NEW.canceled,
updated_at = NEW.updated_at,
published = NEW.published
WHERE id = OLD.id;
RETURN NEW;
END $$;
Вот создание триггера
CREATE TRIGGER invitations_event_view_on_update_trigger
INSTEAD OF UPDATE ON invitations_event_view
FOR EACH ROW EXECUTE FUNCTION invitations_event_view_on_update();
У меня вопрос, как я могу увеличить производительность этой функции?
Думаю, это потому, что я установил все поля, а не только обновления, но я не уверен на 100%. Если бы специалисты могли подсказать, было бы здорово.
EDIT
Попробуйте с prepare
.
CREATE OR REPLACE FUNCTION invitations_event_view_on_update() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
PREPARE event_update(bigint, bigint, character varying, timestamp without time zone, timestamp without time zone, integer, integer, boolean, timestamp without time zone, text, timestamp without time zone, boolean, integer) AS
UPDATE events
SET establishment_id = $2,
name = $3,
start_at = $4,
end_at = $5,
canceled = $6,
updated_at = $7,
published = $8
WHERE id = $1;
EXECUTE event_update(OLD.id, NEW.establishment_id, NEW.name, NEW.start_at, NEW.end_at, NEW.canceled, NEW.updated_at, NEW.published);
DEALLOCATE PREPARE event_update;
RETURN NEW;
END
$$;