Skip to content

PostgreSQL — Basics

  • Process-per-connection (forked). Heavy → put PgBouncer in front.
  • WAL for durability. fsync on commit.
  • Shared buffers ~25% of RAM. Background writers, autovacuum, checkpointer.
  • Numeric: int2/4/8, numeric(p,s), real, double precision.
  • Text: text (preferred), varchar(n). No perf diff.
  • Time: timestamptz (always — UTC stored), date, interval.
  • JSON: jsonb (binary, indexable). Never json.
  • Arrays, UUID, citext, range, geometric, network, enum.

PRIMARY KEY, UNIQUE, NOT NULL, CHECK, FOREIGN KEY. Deferrable for cycles. EXCLUDE USING gist for no-overlap (e.g., time ranges).

TypeUse
B-tree (default)equality, range, ORDER BY, LIKE 'foo%'
Hashequality only (rarely beats B-tree)
GINjsonb, arrays, full-text
GiSTgeo, full-text, exclusion, ranges
SP-GiSTpartitioned space (IPs, phone)
BRINhuge ordered tables (timestamps); tiny
  • Partial: WHERE deleted_at IS NULL — index subset.
  • Covering: INCLUDE (col) — index-only scan.
  • Expression: ON users (lower(email)).
  • Multi-col: leftmost-prefix only.

Inner, Left, Right, Full Outer, Cross, Lateral, Self. Planner picks: nested loop, hash, merge.

BEGIN/COMMIT/ROLLBACK. Savepoints. Default = Read Committed.

LevelPrevents
Read Committeddirty reads
Repeatable Read+ non-repeatable + phantom (PG snapshot)
Serializable+ serialization anomalies (SSI). Retry on 40001.
  • CTE: WITH foo AS (...). PG 12+ inlines simple ones.
  • Window: ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...), LAG, LEAD.
  • RETURNING *, INSERT ... ON CONFLICT (col) DO UPDATE (upsert).
  • DISTINCT ON (col), LATERAL.

NULL = NULL is NULL. Use IS NULL / IS DISTINCT FROM. count(col) skips, count(*) doesn’t.

Roles, schemas, GRANT/REVOKE. Row-level security via CREATE POLICY.