PostgreSQL: PostgreSQL Getting Started
PostgreSQL is the world's most advanced open-source relational database. Renowned for its reliability, extensibility, and standards compliance, it is trusted by global leaders like Apple, Instagram, and Spotify.
1. What You'll Learn
- What a database is, and the difference between relational and non-relational
- PostgreSQL's history and design philosophy
- PostgreSQL vs MySQL: the key differences
- PostgreSQL's core strengths (ACID / MVCC / extensibility / JSONB / full-text search)
- Common use cases for PostgreSQL
2. A Full-Stack Developer's Real Story
(1) The Pain: Database Selection Is Confusing
Alice is a full-stack developer whose company is launching a new e-commerce project. At the tech selection meeting, the team argued back and forth between MySQL and PostgreSQL:
- Some insisted on MySQL: "We've always used MySQL—no need to switch."
- Others recommended PostgreSQL: "PG supports JSONB, full-text search, and window functions—far more capable than MySQL."
- Alice was confused: what is the essential difference between the two? If they chose wrong, would the migration cost be high later?
She needed an objective, comprehensive comparison to make the decision.
(2) PostgreSQL's Solution
PostgreSQL covers most business needs with a single database—from traditional relational queries to JSON document storage, from full-text search to vector retrieval—without extra middleware:
-- PostgreSQL: one database for multiple use cases
-- 1. Traditional relational query
SELECT u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.name;
-- 2. JSONB flexible storage (no need for MongoDB)
INSERT INTO products (name, attributes)
VALUES ('Running Shoes', '{"color": "red", "size": 42, "tags": ["sport", "outdoor"]}'::jsonb);
-- 3. Full-text search (no need for Elasticsearch)
SELECT name FROM products
WHERE to_tsvector('english', name) @@ to_tsquery('english', 'running & shoes');
(3) The Payoff
Alice realized that choosing PostgreSQL meant:
- Maintain 2–3 fewer middleware components (no need for MongoDB / Elasticsearch / Redis cache layer)
- Higher development efficiency: JSONB + full-text search + window functions solve complex needs in a single SQL statement
- Lower long-term cost: PostgreSQL is fully open source and free, with no licensing fees
3. What Is a Database
A database is a system that organizes, stores, and manages data in a structured way. Without a database, an application's data can only live in memory—and disappears the moment the program closes.
(1) Relational vs Non-Relational Databases
| Dimension | Relational (RDBMS) | Non-relational (NoSQL) |
|---|---|---|
| Data model | Tables (rows + columns), strict schema | Document / key-value / graph / wide-column, flexible schema |
| Query language | SQL (standardized) | Proprietary APIs |
| Transactions | ACID strong consistency | Mostly eventual consistency only |
| Examples | PostgreSQL, MySQL, Oracle | MongoDB, Redis, Cassandra |
| Use cases | Complex queries, transaction processing, high consistency needs | High throughput, flexible structure, rapid iteration |
| Scaling | Mostly vertical | Mostly horizontal |
graph TB
DB[Database] --> RDBMS[Relational DB<br/>SQL + ACID]
DB --> NoSQL[NoSQL<br/>Flexible Schema]
RDBMS --> PG[PostgreSQL]
RDBMS --> MY[MySQL]
RDBMS --> OR[Oracle]
NoSQL --> MGO[MongoDB<br/>Document]
NoSQL --> RED[Redis<br/>Key-Value]
NoSQL --> CAS[Cassandra<br/>Wide-Column]
4. PostgreSQL's History
(1) From POSTGRES to PostgreSQL
graph LR
A["1986<br/>POSTGRES project<br/>UC Berkeley"] --> B["1995<br/>Postgres95<br/>Added SQL support"]
B --> C["1996<br/>PostgreSQL 6.0<br/>Open Source release"]
C --> D["2010s<br/>JSONB / CTE / Window<br/>Functions / FDW"]
D --> E["2024<br/>PostgreSQL 17<br/>Current LTS release"]
| Year | Milestone | Significance |
|---|---|---|
| 1986 | POSTGRES project launched | Started by Michael Stonebraker at UC Berkeley, inspired by Ingres |
| 1995 | Postgres95 released | Added SQL language support (replacing the PostQUEL query language) |
| 1996 | PostgreSQL 6.0 | Officially renamed PostgreSQL, released as open source |
| 2005 | Version 8.0 | Native Windows support, savepoints, two-phase commit |
| 2012 | Version 9.2 | JSON support (upgraded to JSONB in 9.4), range types |
| 2016 | Version 9.6 | Parallel queries, phrase full-text search |
| 2017 | Version 10.0 | Declarative partitioning, logical replication, SCRAM auth |
| 2022 | Version 15.0 | MERGE command (SQL-standard UPSERT) |
| 2024 | Version 17.0 | Current LTS release, enhanced logical replication, complete SQL/JSON standard |
(2) PostgreSQL's Design Philosophy
PostgreSQL's core design philosophy can be summed up in four words:
| Principle | Embodied in |
|---|---|
| Standards compliance | Strictly follows the SQL standard (SQL:2023), supports most standard features |
| Extensibility | Supports custom types, functions, index methods, and procedural languages (via Extensions) |
| Reliability | ACID transactions, MVCC concurrency control, WAL write-ahead logging—data is not lost by default |
| Community-driven | No single company in control; 1000+ global contributors; truly open source |
5. PostgreSQL vs MySQL
This is what Alice and her team cared about most. Here's an objective comparison across several dimensions:
| Dimension | PostgreSQL | MySQL |
|---|---|---|
| Architecture | Process model (one process per connection) | Thread model (one thread per connection) |
| Concurrency | MVCC (multi-version concurrency control); reads and writes don't block each other | Mainly table locks; InnoDB row locks but limited range |
| SQL standard | Strictly follows SQL:2023 | Partially follows; many MySQL-specific syntaxes |
| JSON support | JSONB (binary storage, very fast indexed queries) | JSON (text storage, limited features) |
| Full-text search | Built-in tsvector/tsquery, multilingual support | FULLTEXT index, basic features |
| Index types | 6 types (B-Tree / GIN / GiST / BRIN / SP-GiST / Hash) | 3 types (B-Tree / Hash / Fulltext) |
| Extension ecosystem | CREATE EXTENSION installs features in one step (pgvector / PostGIS, etc.) | No equivalent mechanism |
| Partitioning | Declarative partitioning (RANGE / LIST / HASH, PG 10+) | Partitioned tables (8.0+), more verbose syntax |
| Replication | Streaming + logical replication (replicate per table) | Master-slave replication (whole instance) |
| Backup | PITR point-in-time recovery (to the second) | binlog replay (coarser) |
| License | PostgreSQL License (BSD-like, very permissive) | GPL (commercial restrictions) |
| Complex queries | Window functions / recursive CTE / LATERAL JOIN natively supported | Supported from 8.0+ but weaker than PG |
| Operations | Many config options, large tuning headroom | Works out of the box, simpler ops |
| Market share | Fastest-growing database on DB-Engines for 7 consecutive years | Largest global install base |
▶ Example: UPSERT Syntax Comparison
-- PostgreSQL: INSERT ON CONFLICT (more flexible)
INSERT INTO users (email, name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email)
DO UPDATE SET name = EXCLUDED.name, updated_at = NOW()
RETURNING id, name, updated_at;
-- RETURNING clause returns the affected row (MySQL has no equivalent)
Output:
INSERT 0 1
-- MySQL: ON DUPLICATE KEY UPDATE (less flexible)
INSERT INTO users (email, name)
VALUES ('alice@example.com', 'Alice')
ON DUPLICATE KEY UPDATE name = VALUES(name), updated_at = NOW();
-- No RETURNING clause, must run a separate SELECT to get the result
▶ Example: JSONB Query Comparison
-- PostgreSQL: JSONB with GIN index (fast indexed queries)
SELECT name FROM products
WHERE attributes @> '{"color": "red"}'::jsonb;
-- @> is the "contains" operator, uses GIN index
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
-- MySQL: JSON function (no index support for this pattern)
SELECT name FROM products
WHERE JSON_CONTAINS(attributes, '"red"', '$.color');
-- No index, full table scan
▶ Example: Full-Text Search Comparison
-- PostgreSQL: built-in full-text search with ranking
SELECT name, ts_rank(to_tsvector('english', name || ' ' || description),
to_tsquery('english', 'red & shoes')) AS rank
FROM products
WHERE to_tsvector('english', name || ' ' || description)
@@ to_tsquery('english', 'red & shoes')
ORDER BY rank DESC;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
-- MySQL: basic FULLTEXT search (no ranking flexibility)
SELECT name FROM products
WHERE MATCH(name, description) AGAINST('red shoes' IN BOOLEAN MODE);
6. PostgreSQL's Core Strengths
(1) ACID Transactions
ACID is the set of four properties that guarantee data reliability:
| Property | Full name | Meaning | PostgreSQL implementation |
|---|---|---|---|
| A | Atomicity | All-or-nothing: a transaction either fully succeeds or fully rolls back | WAL write-ahead log |
| C | Consistency | The database remains in a valid state before and after a transaction | Constraints / triggers / type checks |
| I | Isolation | Concurrent transactions don't interfere with each other | MVCC multi-version concurrency control |
| D | Durability | Committed data is never lost | WAL + fsync |
(2) MVCC Multi-Version Concurrency Control
MVCC is the core of PostgreSQL's concurrency. Reads don't block writes, and writes don't block reads:
| Scenario | MySQL (InnoDB) | PostgreSQL (MVCC) |
|---|---|---|
| Read-write concurrency | Shared/exclusive locks, possible blocking | Readers see a snapshot; writers create new versions—no blocking |
| Long transaction impact | Blocks other transactions | No blocking; only old versions are retained |
| Consistent read | Needs MVCC but complex to implement | Natural snapshot isolation |
(3) Extensibility
PostgreSQL's extension mechanism (CREATE EXTENSION) is its biggest ecosystem advantage:
| Extension | Function | Replaces middleware |
|---|---|---|
| pgvector | Vector search / AI embeddings | Pinecone / Weaviate |
| PostGIS | Geospatial queries | MongoDB Geo |
| pg_trgm | Fuzzy search | Elasticsearch |
| pgcrypto | Encryption functions | Application-layer encryption |
| uuid-ossp | UUID generation | Application-layer generation |
| postgres_fdw | Cross-database queries | ETL tools |
▶ Example: Installing and Using Extensions
-- Check available extensions
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('uuid-ossp', 'pg_trgm', 'pgcrypto');
-- Install an extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Use the extension to generate UUIDs
SELECT uuid_generate_v4();
-- Output: a unique UUID like 550e8400-e29b-41d4-a716-446655440000
Output:
CREATE TABLE
▶ Example: Conditional Aggregation with FILTER
-- PostgreSQL: FILTER clause for conditional aggregation (SQL standard)
SELECT
store_id,
COUNT(*) AS total_orders,
COUNT(*) FILTER (WHERE status = 'completed') AS completed_orders,
COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled_orders
FROM orders
GROUP BY store_id;
Output:
count
-------
5
(1 row)
-- MySQL: must use SUM(IF()) or SUM(CASE) workaround
SELECT
store_id,
COUNT(*) AS total_orders,
SUM(IF(status = 'completed', 1, 0)) AS completed_orders,
SUM(IF(status = 'cancelled', 1, 0)) AS cancelled_orders
FROM orders
GROUP BY store_id;
7. Common Use Cases for PostgreSQL
| Scenario | PG feature | Example |
|---|---|---|
| E-commerce | JSONB product attributes + full-text search + partitioning | Dynamic SKU attributes, product search, monthly-partitioned orders |
| SaaS multi-tenant | RLS row-level security + schema isolation | One database serving many tenants, row-level policies isolate data |
| Data analytics | Window functions + materialized views + CTE | User retention analysis, sales trend reports, complex stats |
| AI / recommendation | pgvector vector search | Product similarity, semantic search, RAG apps |
| GIS services | PostGIS extension | Map apps, distance calc, route planning |
| Finance | ACID + 3-level isolation + PITR | Transfers, reconciliation, point-in-time recovery |
| Content management | Full-text search + JSONB | Article search, tag management, flexible content |
▶ Example: E-commerce—JSONB for Product Attributes
-- Different products have different attributes
-- No need for separate tables or columns for each attribute type
INSERT INTO products (name, price, attributes) VALUES
('Running Shoes', 89.99, '{"color": "red", "size": 42, "weight_grams": 280}'::jsonb),
('Laptop', 1299.00, '{"cpu": "M3", "ram_gb": 16, "screen_inch": 14}'::jsonb),
('Coffee Beans', 24.50, '{"origin": "Colombia", "roast": "medium", "weight_kg": 1}'::jsonb);
-- Query: find all red products under $100
SELECT name, price, attributes
FROM products
WHERE price < 100
AND attributes @> '{"color": "red"}'::jsonb;
Output:
name | price | attributes
---------------+--------+--------------------------------------------
Running Shoes | 89.99 | {"color": "red", "size": 42, "weight_grams": 280}
8. Complete Example: Database Selection Decision Flow
-- ============================================
-- Comprehensive example: PostgreSQL feature demo
-- Shows why one PG database can replace multiple tools
-- ============================================
-- 1. ACID transaction (no need for application-level consistency)
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT;
-- 2. JSONB storage (no need for MongoDB)
INSERT INTO products (name, attributes)
VALUES ('Smart Watch', '{"color": "black", "battery_life_hours": 48, "waterproof": true}'::jsonb);
-- 3. Full-text search (no need for Elasticsearch)
SELECT name, ts_rank(
to_tsvector('english', name),
plainto_tsquery('english', 'smart watch')
) AS relevance
FROM products
WHERE to_tsvector('english', name) @@ plainto_tsquery('english', 'smart watch')
ORDER BY relevance DESC;
-- 4. Window function (no need for application-level ranking)
SELECT name, price,
RANK() OVER (ORDER BY price DESC) AS price_rank
FROM products;
-- 5. UPSERT (no need for application-level conflict handling)
INSERT INTO products (name, price, attributes)
VALUES ('Smart Watch', 199.99, '{"color": "black", "battery_life_hours": 48}'::jsonb)
ON CONFLICT (name)
DO UPDATE SET price = EXCLUDED.price,
attributes = EXCLUDED.attributes
RETURNING id, name, price;
Output (excerpt):
-- UPSERT RETURNING output:
id | name | price
----+-------------+--------
1 | Smart Watch | 199.99
❓ FAQ
📖 Summary
- PostgreSQL is the world's most advanced open-source relational database and strictly follows the SQL standard
- PG evolved from POSTGRES in 1986 to PostgreSQL 17 in 2024, continuously improving
- PG vs MySQL: PG leads in complex queries, JSONB, full-text search, the extension ecosystem, and data integrity; MySQL wins in simple scenarios and operational simplicity
- PG's core strengths: ACID transactions, MVCC concurrency control, the extension mechanism, JSONB, and full-text search
- One PG database can replace several middleware components (MongoDB + Elasticsearch + Redis), reducing operational complexity
- PG use cases: e-commerce, SaaS, data analytics, AI recommendation, GIS, finance, content management
📝 Exercises
-
Basic (★): List 3 features that make PostgreSQL unique compared to MySQL (features MySQL lacks or where it's significantly weaker), and in one sentence explain the benefit of each.
-
Intermediate (★★): Suppose you're choosing a database for an online education platform that needs to store course info (structured) and student notes (unstructured), plus search course content. Write your reason for choosing PostgreSQL or MySQL, citing at least 3 technical features to support your argument.
-
Challenge (★★★): Read the PostgreSQL docs "Feature Matrix" page (search "PostgreSQL Feature Matrix") and find 3 PG features not mentioned in this lesson, explaining what external tool or middleware each can replace.