SlideShare une entreprise Scribd logo
1  sur  43
Télécharger pour lire hors ligne
Introduction to
Triggers
Who am I?
• Jim Mlodgenski
– jimm@openscg.com
– @jim_mlodgenski
• Director
– United States PostgreSQL (www.postgresql.us)
• Co-organizer of
– Philly PUG (www.phlpug.org)
– NYC PUG (www.nycpug.org)
• CTO, OpenSCG
– www.openscg.com
Triggers
• Code that gets executed when an
event happens in the database
– INSERT, UPDATE, DELETE
• Event Triggers fire on DDL
– CREATE, DROP, ALTER
– Still not mature yet
●
(limited functionaity)
Use Cases
• Table Partitioning
• Automatically generate derived column
values
• Enforce complex constraints
• Enforce referential integrity across nodes in a
distributed database
• Provide transparent event logging
• Provide auditing
• Invalidate cache entries
Structure
● Trigger
● Trigger Function
CREATE TRIGGER foo_trg
BEFORE UPDATE ON foo
FOR EACH ROW
EXECUTE PROCEDURE
foo_update();
Trigger Events
● Insert
● Update
● Delete
● Truncate
Trigger Timing
● Before
– The trigger is fired before the change is made
to the table
● After
– The trigger is fired after the change is made to
the table
Trigger Frequency
● For Each Row
– The trigger is fired once each time a row is
affected
● For Each Statement
– The trigger is fired once each time a statement
is executed
Trigger Overhead
CREATE UNLOGGED TABLE trigger_test (
key serial primary key,
value varchar,
insert_ts timestamp,
update_ts timestamp
);
INSERT INTO trigger_test (value) VALUES
(‘hello’);
set keys :scale
setrandom key 1 :keys
UPDATE trigger_test SET value = 'HELLO' WHERE
key = :key;
Trigger Overhead
pgbench -n -t 100000
-f INSERTS.pgbench postgres
pgbench -n -s 100000 -t 10000
-f UPDATES.pgbench postgres
Inserts: 4510 tps
Updates: 4349 tps
Trigger Overhead
CREATE FUNCTION empty_trigger()
RETURNS trigger AS $$
BEGIN
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER empty_trigger BEFORE
INSERT OR UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE
empty_trigger();
Trigger Overhead
pgbench -n -t 100000
-f INSERTS.pgbench postgres
pgbench -n -s 100000 -t 10000
-f UPDATES.pgbench postgres
Inserts: 4296 tps (4.8% overhead)
Updates: 3988 tps (8.3% overhead)
Trigger Arguments
● NEW
– Variable holding the new row for
INSERT/UPDATE operations in row-level triggers
● OLD
– Variable holding the old row for UPDATE/DELETE
operations in row-level triggers
NEW vs OLD
CREATE TABLE audit (
event_time timestamp NOT NULL,
user_name varchar NOT NULL,
old_row json,
new_row json
);
NEW vs OLD (cont.)
CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP,
CURRENT_USER,
row_to_json(OLD),
row_to_json(NEW));
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
NEW vs OLD (cont.)
CREATE TRIGGER audit_trigger
AFTER UPDATE ON pgbench_branches
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
Trigger Arguments (cont.)
● TG_OP
– A string of INSERT, UPDATE, DELETE, or TRUNCATE
telling for which operation the trigger was fired
● TG_NAME
– Variable that contains the name of the trigger actually
fired
● TG_WHEN
– A string of BEFORE, AFTER, or INSTEAD OF, depending
on the trigger's definition
● TG_LEVEL
– A string of either ROW or STATEMENT depending on the
trigger's definition
TG_OP
CREATE TABLE audit (
event_time timestamp NOT NULL,
user_name varchar NOT NULL,
operation varchar NOT NULL,
old_row json,
new_row json
);
TG_OP (cont.)
CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
row_to_json(OLD), null);
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
row_to_json(OLD), row_to_json(NEW));
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
null, row_to_json(NEW));
RETURN NEW;
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
TG_OP (cont.)
CREATE TRIGGER audit_trigger
AFTER UPDATE OR INSERT OR DELETE
ON pgbench_branches
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
Trigger Arguments (cont.)
● TG_TABLE_NAME
– The name of the table that caused the trigger
invocation.
● TG_RELNAME
– The name of the table that caused the trigger
invocation
● TG_RELID
– The object ID of the table that caused the trigger
invocation
● TG_TABLE_SCHEMA
– The name of the schema of the table that caused the
trigger invocation
TG_TABLE_NAME
CREATE TABLE audit (
event_time timestamp NOT NULL,
user_name varchar NOT NULL,
operation varchar NOT NULL,
table_name varchar NOT NULL,
old_row json,
new_row json
);
TG_TABLE_NAME (cont.)
CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
TG_TABLE_NAME, row_to_json(OLD), null);
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
TG_TABLE_NAME, row_to_json(OLD), row_to_json(NEW));
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
TG_TABLE_NAME, null, row_to_json(NEW));
RETURN NEW;
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
TG_TABLE_NAME (cont.)
CREATE TRIGGER audit_trigger
AFTER UPDATE OR INSERT OR DELETE
ON pgbench_branches
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
CREATE TRIGGER audit_trigger
AFTER UPDATE OR INSERT OR DELETE
ON pgbench_tellers
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
Trigger Arguments (cont.)
● TG_NARGS
– The number of arguments given to the trigger
procedure in the CREATE TRIGGER statement
● TG_ARGV[]
– The arguments from the CREATE TRIGGER
statement
Trigger Use Cases
● Table Partitioning
– Splitting what is logically one large table into
smaller physical pieces
– Used to:
● Increase performance
● Archive data
● Storage tiering
Table Partitioning
CREATE TABLE audit_2014 (
CHECK ( event_time >= DATE '2014-01-01'
AND event_time < DATE '2015-01-01')
) INHERITS (audit);
CREATE TABLE audit_2015 (
CHECK ( event_time >= DATE '2015-01-01'
AND event_time < DATE '2016-01-01')
) INHERITS (audit);
Table Partitioning (cont.)
CREATE OR REPLACE FUNCTION partition_audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
EXECUTE 'INSERT INTO audit_' ||
to_char(NEW.event_time, 'YYYY') ||
' VALUES ($1, $2, $3, $4, $5, $6)'
USING NEW.event_time, NEW.user_name, NEW.operation,
NEW.table_name, NEW.old_row, NEW.new_row;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Table Partitioning (cont.)
CREATE TRIGGER partition_audit_trigger
BEFORE INSERT ON audit
FOR EACH ROW
EXECUTE PROCEDURE
partition_audit_trigger();
Partitioning Performance
CREATE OR REPLACE FUNCTION partition_audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF ( NEW.event_time >= DATE '2015-01-01' AND
NEW.event_time < DATE '2016-01-01' ) THEN
INSERT INTO audit_2015 VALUES (NEW.*);
ELSIF ( NEW.event_time >= DATE '2014-01-01' AND
NEW.event_time < DATE '2015-01-01' ) THEN
INSERT INTO audit_2014 VALUES (NEW.*);
ELSE
RAISE EXCEPTION 'Date out of range. Fix
partition_audit_trigger() function!';
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Moving Partitions
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2014
FOR EACH ROW EXECUTE PROCEDURE
move_partition_audit_trigger('2014-01-01', '2015-01-01');
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2015
FOR EACH ROW EXECUTE PROCEDURE
move_partition_audit_trigger('2015-01-01', '2016-01-01');
Moving Partitions (cont.)
CREATE OR REPLACE FUNCTION move_partition_audit_trigger()
RETURNS TRIGGER AS $$
DECLARE
start_date DATE;
end_date DATE;
BEGIN
start_date := TG_ARGV[0];
end_date := TG_ARGV[1];
IF ( NEW.event_time IS DISTINCT FROM OLD.event_time ) THEN
IF (NEW.event_time < start_date OR NEW.event_time >= end_date) THEN
EXECUTE 'DELETE FROM ' || TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME ||
' WHERE ctid = $1'
USING OLD.ctid;
INSERT INTO audit VALUES (NEW.*);
RETURN null;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Moving Partitions (cont.)
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2014
FOR EACH ROW
WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time)
EXECUTE PROCEDURE
move_partition_audit_trigger('2014-01-01', '2015-01-01');
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2015
FOR EACH ROW
WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time)
EXECUTE PROCEDURE
move_partition_audit_trigger('2015-01-01', '2016-01-01');
Trigger Use Cases
● Calculate columns
– Calculate complex values
– Extract values from complex structures
– Used to:
● Increase performance
● Simplify queries
Extract JSON
$ head -n 5 zips.json
{ "_id" : "01001", "city" : "AGAWAM",
"loc" : [ -72.622739, 42.070206 ], "pop" : 15338, "state" : "MA" }
{ "_id" : "01002", "city" : "CUSHMAN",
"loc" : [ -72.51564999999999, 42.377017 ], "pop" : 36963, "state" : "MA" }
{ "_id" : "01005", "city" : "BARRE",
"loc" : [ -72.10835400000001, 42.409698 ], "pop" : 4546, "state" : "MA" }
{ "_id" : "01007", "city" : "BELCHERTOWN",
"loc" : [ -72.41095300000001, 42.275103 ], "pop" : 10579, "state" : "MA" }
{ "_id" : "01008", "city" : "BLANDFORD",
"loc" : [ -72.936114, 42.182949 ], "pop" : 1240, "state" : "MA" }
CREATE TABLE zips (
zip_code varchar PRIMARY KEY,
state varchar,
data json
);
Extract JSON
CREATE OR REPLACE FUNCTION extract_data_trigger()
RETURNS TRIGGER AS $$
BEGIN
NEW.zip_code := NEW.data->>'_id';
NEW.state := NEW.data->>'state';
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER extract_data_trigger
BEFORE UPDATE OR INSERT
ON zips
FOR EACH ROW EXECUTE PROCEDURE extract_data_trigger();
Trigger Use Cases
● Cache invalidation
– Remove stale entries from a cache
– The database tracks all data so is the single
source of truth
– Used to:
● Simplify cache management
● Remove application complexity
Note: Foreign Data Wrappers simplify this
process significantly
Cache Invalidation
CREATE TABLE users (
id serial PRIMARY KEY,
first_name varchar,
last_name varchar,
email_address varchar NOT NULL,
password_md5 varchar NOT NULL
);
CREATE OR REPLACE FUNCTION remove_cache_trigger()
RETURNS TRIGGER AS $$
BEGIN
DELETE from myredis_cache
WHERE key = OLD.id::varchar;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER remove_cache_trigger
AFTER UPDATE OR DELETE
ON users
FOR EACH ROW EXECUTE PROCEDURE remove_cache_trigger();
Cache Invalidation - Async
CREATE OR REPLACE FUNCTION remove_cache_trigger()
RETURNS TRIGGER AS $$
BEGIN
PERFORM pg_notify(TG_TABLE_NAME, OLD.id::varchar);
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Things to Remember
● Triggers are part of the parent
transaction
– The trigger fails, the main transaction fails
– If the trigger takes a long time, the whole
transaction timing is affected
● Triggers can be difficult to debug
– Especially cascaded triggers
Trigger Function Language
Questions?

Contenu connexe

Tendances

Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013Jaime Crespo
 
Advanced MySQL Query Tuning
Advanced MySQL Query TuningAdvanced MySQL Query Tuning
Advanced MySQL Query TuningAlexander Rubin
 
[Pgday.Seoul 2018] 이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
[Pgday.Seoul 2018]  이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG[Pgday.Seoul 2018]  이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
[Pgday.Seoul 2018] 이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PGPgDay.Seoul
 
Postgresql Database Administration Basic - Day1
Postgresql  Database Administration Basic  - Day1Postgresql  Database Administration Basic  - Day1
Postgresql Database Administration Basic - Day1PoguttuezhiniVP
 
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...Citus Data
 
Postgres connections at scale
Postgres connections at scalePostgres connections at scale
Postgres connections at scaleMydbops
 
SQL Server Blocking Analysis
SQL Server Blocking AnalysisSQL Server Blocking Analysis
SQL Server Blocking AnalysisHậu Võ Tấn
 
Mvcc in postgreSQL 권건우
Mvcc in postgreSQL 권건우Mvcc in postgreSQL 권건우
Mvcc in postgreSQL 권건우PgDay.Seoul
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQLJoel Brewer
 
Getting started with postgresql
Getting started with postgresqlGetting started with postgresql
Getting started with postgresqlbotsplash.com
 
MySQL Advanced Administrator 2021 - 네오클로바
MySQL Advanced Administrator 2021 - 네오클로바MySQL Advanced Administrator 2021 - 네오클로바
MySQL Advanced Administrator 2021 - 네오클로바NeoClova
 
MySQL Architecture and Engine
MySQL Architecture and EngineMySQL Architecture and Engine
MySQL Architecture and EngineAbdul Manaf
 
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres OpenKevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres OpenPostgresOpen
 
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기PgDay.Seoul
 

Tendances (20)

Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
 
Advanced MySQL Query Tuning
Advanced MySQL Query TuningAdvanced MySQL Query Tuning
Advanced MySQL Query Tuning
 
PostgreSQL and RAM usage
PostgreSQL and RAM usagePostgreSQL and RAM usage
PostgreSQL and RAM usage
 
[Pgday.Seoul 2018] 이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
[Pgday.Seoul 2018]  이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG[Pgday.Seoul 2018]  이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
[Pgday.Seoul 2018] 이기종 DB에서 PostgreSQL로의 Migration을 위한 DB2PG
 
Postgresql Database Administration Basic - Day1
Postgresql  Database Administration Basic  - Day1Postgresql  Database Administration Basic  - Day1
Postgresql Database Administration Basic - Day1
 
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
JSONB Tricks: Operators, Indexes, and When (Not) to Use It | PostgresOpen 201...
 
Pro Postgres 9
Pro Postgres 9Pro Postgres 9
Pro Postgres 9
 
Postgres connections at scale
Postgres connections at scalePostgres connections at scale
Postgres connections at scale
 
SQL Server Blocking Analysis
SQL Server Blocking AnalysisSQL Server Blocking Analysis
SQL Server Blocking Analysis
 
Mvcc in postgreSQL 권건우
Mvcc in postgreSQL 권건우Mvcc in postgreSQL 권건우
Mvcc in postgreSQL 권건우
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQL
 
MySQL lecture
MySQL lectureMySQL lecture
MySQL lecture
 
Backup and-recovery2
Backup and-recovery2Backup and-recovery2
Backup and-recovery2
 
PostgreSQL
PostgreSQLPostgreSQL
PostgreSQL
 
Getting started with postgresql
Getting started with postgresqlGetting started with postgresql
Getting started with postgresql
 
MySQL Advanced Administrator 2021 - 네오클로바
MySQL Advanced Administrator 2021 - 네오클로바MySQL Advanced Administrator 2021 - 네오클로바
MySQL Advanced Administrator 2021 - 네오클로바
 
Unit 2 oracle9i
Unit 2  oracle9i Unit 2  oracle9i
Unit 2 oracle9i
 
MySQL Architecture and Engine
MySQL Architecture and EngineMySQL Architecture and Engine
MySQL Architecture and Engine
 
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres OpenKevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
 
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
 

Similaire à An Introduction To PostgreSQL Triggers

Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17Thuan Nguyen
 
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres OpenKeith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres OpenPostgresOpen
 
Major features postgres 11
Major features postgres 11Major features postgres 11
Major features postgres 11EDB
 
Procedures and triggers in SQL
Procedures and triggers in SQLProcedures and triggers in SQL
Procedures and triggers in SQLVikash Sharma
 
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracleprohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for OracleJacek Gebal
 
PostgreSQL 9.5 Features
PostgreSQL 9.5 FeaturesPostgreSQL 9.5 Features
PostgreSQL 9.5 FeaturesSaiful
 
Oracle trigger
Oracle triggerOracle trigger
Oracle triggernasrul28
 
Function Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdfFunction Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdfSanam Maharjan
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq lsInSync Conference
 
Database Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event SchedulersDatabase Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event SchedulersAbdul Rahman Sherzad
 
Changing your huge table's data types in production
Changing your huge table's data types in productionChanging your huge table's data types in production
Changing your huge table's data types in productionJimmy Angelakos
 
Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14Leon Rzhemovskiy
 
Below is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdfBelow is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdfaroraenterprisesmbd
 
T sql denali code Day of .Net
T sql denali code Day of .NetT sql denali code Day of .Net
T sql denali code Day of .NetKathiK58
 
Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009mattsmiley
 

Similaire à An Introduction To PostgreSQL Triggers (20)

Unit 4
Unit 4Unit 4
Unit 4
 
Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17
 
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres OpenKeith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
 
Major features postgres 11
Major features postgres 11Major features postgres 11
Major features postgres 11
 
Procedures and triggers in SQL
Procedures and triggers in SQLProcedures and triggers in SQL
Procedures and triggers in SQL
 
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracleprohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
 
PostgreSQL 9.5 Features
PostgreSQL 9.5 FeaturesPostgreSQL 9.5 Features
PostgreSQL 9.5 Features
 
Oracle trigger
Oracle triggerOracle trigger
Oracle trigger
 
Function Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdfFunction Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdf
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
 
Database Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event SchedulersDatabase Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event Schedulers
 
Changing your huge table's data types in production
Changing your huge table's data types in productionChanging your huge table's data types in production
Changing your huge table's data types in production
 
Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14
 
Triggers
TriggersTriggers
Triggers
 
Below is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdfBelow is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdf
 
T sql denali code Day of .Net
T sql denali code Day of .NetT sql denali code Day of .Net
T sql denali code Day of .Net
 
Basic Query Tuning Primer
Basic Query Tuning PrimerBasic Query Tuning Primer
Basic Query Tuning Primer
 
Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009
 
Good Tests Bad Tests
Good Tests Bad TestsGood Tests Bad Tests
Good Tests Bad Tests
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 

Plus de Jim Mlodgenski

Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLTop 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLJim Mlodgenski
 
Oracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakesOracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakesJim Mlodgenski
 
Debugging Your PL/pgSQL Code
Debugging Your PL/pgSQL CodeDebugging Your PL/pgSQL Code
Debugging Your PL/pgSQL CodeJim Mlodgenski
 
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasPostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasJim Mlodgenski
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQLJim Mlodgenski
 
Leveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentLeveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentJim Mlodgenski
 
Scaling PostreSQL with Stado
Scaling PostreSQL with StadoScaling PostreSQL with Stado
Scaling PostreSQL with StadoJim Mlodgenski
 
Multi-Master Replication with Slony
Multi-Master Replication with SlonyMulti-Master Replication with Slony
Multi-Master Replication with SlonyJim Mlodgenski
 
Scaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQLScaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQLJim Mlodgenski
 

Plus de Jim Mlodgenski (12)

Strategic autovacuum
Strategic autovacuumStrategic autovacuum
Strategic autovacuum
 
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLTop 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
 
Oracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakesOracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakes
 
Profiling PL/pgSQL
Profiling PL/pgSQLProfiling PL/pgSQL
Profiling PL/pgSQL
 
Debugging Your PL/pgSQL Code
Debugging Your PL/pgSQL CodeDebugging Your PL/pgSQL Code
Debugging Your PL/pgSQL Code
 
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasPostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQL
 
Postgresql Federation
Postgresql FederationPostgresql Federation
Postgresql Federation
 
Leveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentLeveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL Environment
 
Scaling PostreSQL with Stado
Scaling PostreSQL with StadoScaling PostreSQL with Stado
Scaling PostreSQL with Stado
 
Multi-Master Replication with Slony
Multi-Master Replication with SlonyMulti-Master Replication with Slony
Multi-Master Replication with Slony
 
Scaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQLScaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQL
 

Dernier

Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 

Dernier (20)

Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 

An Introduction To PostgreSQL Triggers

  • 2. Who am I? • Jim Mlodgenski – jimm@openscg.com – @jim_mlodgenski • Director – United States PostgreSQL (www.postgresql.us) • Co-organizer of – Philly PUG (www.phlpug.org) – NYC PUG (www.nycpug.org) • CTO, OpenSCG – www.openscg.com
  • 3.
  • 4. Triggers • Code that gets executed when an event happens in the database – INSERT, UPDATE, DELETE • Event Triggers fire on DDL – CREATE, DROP, ALTER – Still not mature yet ● (limited functionaity)
  • 5. Use Cases • Table Partitioning • Automatically generate derived column values • Enforce complex constraints • Enforce referential integrity across nodes in a distributed database • Provide transparent event logging • Provide auditing • Invalidate cache entries
  • 6. Structure ● Trigger ● Trigger Function CREATE TRIGGER foo_trg BEFORE UPDATE ON foo FOR EACH ROW EXECUTE PROCEDURE foo_update();
  • 7. Trigger Events ● Insert ● Update ● Delete ● Truncate
  • 8. Trigger Timing ● Before – The trigger is fired before the change is made to the table ● After – The trigger is fired after the change is made to the table
  • 9. Trigger Frequency ● For Each Row – The trigger is fired once each time a row is affected ● For Each Statement – The trigger is fired once each time a statement is executed
  • 10. Trigger Overhead CREATE UNLOGGED TABLE trigger_test ( key serial primary key, value varchar, insert_ts timestamp, update_ts timestamp ); INSERT INTO trigger_test (value) VALUES (‘hello’); set keys :scale setrandom key 1 :keys UPDATE trigger_test SET value = 'HELLO' WHERE key = :key;
  • 11. Trigger Overhead pgbench -n -t 100000 -f INSERTS.pgbench postgres pgbench -n -s 100000 -t 10000 -f UPDATES.pgbench postgres Inserts: 4510 tps Updates: 4349 tps
  • 12. Trigger Overhead CREATE FUNCTION empty_trigger() RETURNS trigger AS $$ BEGIN RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER empty_trigger BEFORE INSERT OR UPDATE ON trigger_test FOR EACH ROW EXECUTE PROCEDURE empty_trigger();
  • 13. Trigger Overhead pgbench -n -t 100000 -f INSERTS.pgbench postgres pgbench -n -s 100000 -t 10000 -f UPDATES.pgbench postgres Inserts: 4296 tps (4.8% overhead) Updates: 3988 tps (8.3% overhead)
  • 14. Trigger Arguments ● NEW – Variable holding the new row for INSERT/UPDATE operations in row-level triggers ● OLD – Variable holding the old row for UPDATE/DELETE operations in row-level triggers
  • 15. NEW vs OLD CREATE TABLE audit ( event_time timestamp NOT NULL, user_name varchar NOT NULL, old_row json, new_row json );
  • 16. NEW vs OLD (cont.) CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$ BEGIN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER, row_to_json(OLD), row_to_json(NEW)); RETURN NEW; END; $$ LANGUAGE plpgsql;
  • 17. NEW vs OLD (cont.) CREATE TRIGGER audit_trigger AFTER UPDATE ON pgbench_branches FOR EACH ROW EXECUTE PROCEDURE audit_trigger();
  • 18. Trigger Arguments (cont.) ● TG_OP – A string of INSERT, UPDATE, DELETE, or TRUNCATE telling for which operation the trigger was fired ● TG_NAME – Variable that contains the name of the trigger actually fired ● TG_WHEN – A string of BEFORE, AFTER, or INSTEAD OF, depending on the trigger's definition ● TG_LEVEL – A string of either ROW or STATEMENT depending on the trigger's definition
  • 19. TG_OP CREATE TABLE audit ( event_time timestamp NOT NULL, user_name varchar NOT NULL, operation varchar NOT NULL, old_row json, new_row json );
  • 20. TG_OP (cont.) CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$ BEGIN IF (TG_OP = 'DELETE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, row_to_json(OLD), null); RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, row_to_json(OLD), row_to_json(NEW)); RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, null, row_to_json(NEW)); RETURN NEW; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 21. TG_OP (cont.) CREATE TRIGGER audit_trigger AFTER UPDATE OR INSERT OR DELETE ON pgbench_branches FOR EACH ROW EXECUTE PROCEDURE audit_trigger();
  • 22. Trigger Arguments (cont.) ● TG_TABLE_NAME – The name of the table that caused the trigger invocation. ● TG_RELNAME – The name of the table that caused the trigger invocation ● TG_RELID – The object ID of the table that caused the trigger invocation ● TG_TABLE_SCHEMA – The name of the schema of the table that caused the trigger invocation
  • 23. TG_TABLE_NAME CREATE TABLE audit ( event_time timestamp NOT NULL, user_name varchar NOT NULL, operation varchar NOT NULL, table_name varchar NOT NULL, old_row json, new_row json );
  • 24. TG_TABLE_NAME (cont.) CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$ BEGIN IF (TG_OP = 'DELETE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, TG_TABLE_NAME, row_to_json(OLD), null); RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, TG_TABLE_NAME, row_to_json(OLD), row_to_json(NEW)); RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, TG_TABLE_NAME, null, row_to_json(NEW)); RETURN NEW; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 25. TG_TABLE_NAME (cont.) CREATE TRIGGER audit_trigger AFTER UPDATE OR INSERT OR DELETE ON pgbench_branches FOR EACH ROW EXECUTE PROCEDURE audit_trigger(); CREATE TRIGGER audit_trigger AFTER UPDATE OR INSERT OR DELETE ON pgbench_tellers FOR EACH ROW EXECUTE PROCEDURE audit_trigger();
  • 26. Trigger Arguments (cont.) ● TG_NARGS – The number of arguments given to the trigger procedure in the CREATE TRIGGER statement ● TG_ARGV[] – The arguments from the CREATE TRIGGER statement
  • 27. Trigger Use Cases ● Table Partitioning – Splitting what is logically one large table into smaller physical pieces – Used to: ● Increase performance ● Archive data ● Storage tiering
  • 28. Table Partitioning CREATE TABLE audit_2014 ( CHECK ( event_time >= DATE '2014-01-01' AND event_time < DATE '2015-01-01') ) INHERITS (audit); CREATE TABLE audit_2015 ( CHECK ( event_time >= DATE '2015-01-01' AND event_time < DATE '2016-01-01') ) INHERITS (audit);
  • 29. Table Partitioning (cont.) CREATE OR REPLACE FUNCTION partition_audit_trigger() RETURNS TRIGGER AS $$ BEGIN EXECUTE 'INSERT INTO audit_' || to_char(NEW.event_time, 'YYYY') || ' VALUES ($1, $2, $3, $4, $5, $6)' USING NEW.event_time, NEW.user_name, NEW.operation, NEW.table_name, NEW.old_row, NEW.new_row; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 30. Table Partitioning (cont.) CREATE TRIGGER partition_audit_trigger BEFORE INSERT ON audit FOR EACH ROW EXECUTE PROCEDURE partition_audit_trigger();
  • 31. Partitioning Performance CREATE OR REPLACE FUNCTION partition_audit_trigger() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.event_time >= DATE '2015-01-01' AND NEW.event_time < DATE '2016-01-01' ) THEN INSERT INTO audit_2015 VALUES (NEW.*); ELSIF ( NEW.event_time >= DATE '2014-01-01' AND NEW.event_time < DATE '2015-01-01' ) THEN INSERT INTO audit_2014 VALUES (NEW.*); ELSE RAISE EXCEPTION 'Date out of range. Fix partition_audit_trigger() function!'; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 32. Moving Partitions CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2014 FOR EACH ROW EXECUTE PROCEDURE move_partition_audit_trigger('2014-01-01', '2015-01-01'); CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2015 FOR EACH ROW EXECUTE PROCEDURE move_partition_audit_trigger('2015-01-01', '2016-01-01');
  • 33. Moving Partitions (cont.) CREATE OR REPLACE FUNCTION move_partition_audit_trigger() RETURNS TRIGGER AS $$ DECLARE start_date DATE; end_date DATE; BEGIN start_date := TG_ARGV[0]; end_date := TG_ARGV[1]; IF ( NEW.event_time IS DISTINCT FROM OLD.event_time ) THEN IF (NEW.event_time < start_date OR NEW.event_time >= end_date) THEN EXECUTE 'DELETE FROM ' || TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME || ' WHERE ctid = $1' USING OLD.ctid; INSERT INTO audit VALUES (NEW.*); RETURN null; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql;
  • 34. Moving Partitions (cont.) CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2014 FOR EACH ROW WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time) EXECUTE PROCEDURE move_partition_audit_trigger('2014-01-01', '2015-01-01'); CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2015 FOR EACH ROW WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time) EXECUTE PROCEDURE move_partition_audit_trigger('2015-01-01', '2016-01-01');
  • 35. Trigger Use Cases ● Calculate columns – Calculate complex values – Extract values from complex structures – Used to: ● Increase performance ● Simplify queries
  • 36. Extract JSON $ head -n 5 zips.json { "_id" : "01001", "city" : "AGAWAM", "loc" : [ -72.622739, 42.070206 ], "pop" : 15338, "state" : "MA" } { "_id" : "01002", "city" : "CUSHMAN", "loc" : [ -72.51564999999999, 42.377017 ], "pop" : 36963, "state" : "MA" } { "_id" : "01005", "city" : "BARRE", "loc" : [ -72.10835400000001, 42.409698 ], "pop" : 4546, "state" : "MA" } { "_id" : "01007", "city" : "BELCHERTOWN", "loc" : [ -72.41095300000001, 42.275103 ], "pop" : 10579, "state" : "MA" } { "_id" : "01008", "city" : "BLANDFORD", "loc" : [ -72.936114, 42.182949 ], "pop" : 1240, "state" : "MA" } CREATE TABLE zips ( zip_code varchar PRIMARY KEY, state varchar, data json );
  • 37. Extract JSON CREATE OR REPLACE FUNCTION extract_data_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.zip_code := NEW.data->>'_id'; NEW.state := NEW.data->>'state'; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER extract_data_trigger BEFORE UPDATE OR INSERT ON zips FOR EACH ROW EXECUTE PROCEDURE extract_data_trigger();
  • 38. Trigger Use Cases ● Cache invalidation – Remove stale entries from a cache – The database tracks all data so is the single source of truth – Used to: ● Simplify cache management ● Remove application complexity Note: Foreign Data Wrappers simplify this process significantly
  • 39. Cache Invalidation CREATE TABLE users ( id serial PRIMARY KEY, first_name varchar, last_name varchar, email_address varchar NOT NULL, password_md5 varchar NOT NULL ); CREATE OR REPLACE FUNCTION remove_cache_trigger() RETURNS TRIGGER AS $$ BEGIN DELETE from myredis_cache WHERE key = OLD.id::varchar; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER remove_cache_trigger AFTER UPDATE OR DELETE ON users FOR EACH ROW EXECUTE PROCEDURE remove_cache_trigger();
  • 40. Cache Invalidation - Async CREATE OR REPLACE FUNCTION remove_cache_trigger() RETURNS TRIGGER AS $$ BEGIN PERFORM pg_notify(TG_TABLE_NAME, OLD.id::varchar); RETURN NEW; END; $$ LANGUAGE plpgsql;
  • 41. Things to Remember ● Triggers are part of the parent transaction – The trigger fails, the main transaction fails – If the trigger takes a long time, the whole transaction timing is affected ● Triggers can be difficult to debug – Especially cascaded triggers