← PostgreSQL DBA← PostgreSQL DBA
PostgreSQL DBAPostgreSQL DBA19 Th7, 2026Jul 19, 202623 phút đọc17 min read

Giới thiệu & Khái niệm RDBMSIntroduction & RDBMS Concepts

Thuộc bộ kiến thức PostgreSQL DBA Roadmap.

Tổng quan

Một RDBMS (Relational Database Management System — hệ quản trị cơ sở dữ liệu quan hệ) lưu trữ dữ liệu dưới dạng tập hợp các bảng (table) — lưới gồm các hàng (row) và cột (column) — và cho phép bạn liên kết bảng này với bảng khác thông qua các giá trị khóa dùng chung, thay vì thông qua con trỏ hay lồng ghép vật lý. Bạn không cần chỉ cho RDBMS biết cách tìm dữ liệu (đi theo con trỏ này, rồi con trỏ kia); bạn chỉ cần nói điều bạn muốn bằng một ngôn ngữ khai báo — SQL (Structured Query Language) — và bộ tối ưu truy vấn (query planner) của database sẽ tự tìm ra cách nhanh nhất để lấy dữ liệu đó. Sự tách biệt giữa “cái gì” và “làm thế nào” này là lý do lớn nhất khiến mô hình quan hệ thống trị việc lưu trữ dữ liệu nghiệp vụ quan trọng suốt hơn năm mươi năm qua: code ứng dụng có thể thay đổi liên tục, nhưng query planner vẫn có thể được viết lại, nâng cấp và tối ưu hóa lại mà không ai phải động vào một câu lệnh SELECT nào.

Database không phải lúc nào cũng hoạt động theo cách này. Trước mô hình quan hệ của Codd (1970), hai cách tiếp cận thống trị là mô hình phân cấp (hierarchical model) (IMS của IBM, 1966) — dữ liệu được tổ chức thành cây nghiêm ngặt, mỗi bản ghi chỉ có đúng một bản ghi cha, giống cấu trúc filesystem — và mô hình mạng (network model) (CODASYL, cuối thập niên 1960) — một đồ thị các bản ghi kết nối bằng con trỏ tường minh, linh hoạt hơn cây nhưng vẫn phải duyệt bằng code đi theo con trỏ. Cả hai đều yêu cầu lập trình viên ứng dụng phải biết bố cục vật lý của dữ liệu và viết code mệnh lệnh (imperative) để đi qua từng liên kết vật lý, từng bản ghi một. Tổ chức lại cấu trúc vật lý — thêm một đường truy cập mới, đổi chuỗi con trỏ — đồng nghĩa phải viết lại mọi chương trình có động đến nó. Điểm mấu chốt trong ý tưởng của Codd là tách biệt cấu trúc logic của dữ liệu (các quan hệ, được định nghĩa bởi cột và ràng buộc) khỏi cách lưu trữ vật lý và đường truy cập, đồng thời để ngôn ngữ truy vấn thể hiện ý định thay vì thao tác điều hướng. Sự tách biệt đó chính là lý do mô hình quan hệ chiến thắng: schema có thể tiến hóa, storage engine có thể được tối ưu, index có thể được thêm vào — tất cả mà không phá vỡ các ứng dụng xây dựng bên trên, miễn là hình dạng logic của dữ liệu (schema) vẫn tương thích.

PostgreSQL là một cách hiện thực hóa mô hình này — nhưng là một cách hiện thực hóa đầy tham vọng. Nó khởi đầu là POSTGRES, một dự án nghiên cứu tại UC Berkeley do Michael Stonebraker dẫn dắt (cũng chính là người đứng sau Ingres, một trong những hệ quản trị quan hệ sớm nhất), được thiết kế rõ ràng để vượt ra ngoài mô hình quan hệ của thập niên 1980 bằng cách hỗ trợ kiểu dữ liệu tự định nghĩa (user-defined type), rule, và khả năng mở rộng. Khi hỗ trợ SQL được thêm vào năm 1995, dự án được đổi tên thành Postgres95, và đến năm 1996 trở thành PostgreSQL dưới sự quản trị cộng đồng mã nguồn mở như hiện nay. Chính “gen” nghiên cứu đó — “để người dùng mở rộng hệ thống kiểu dữ liệu và cả bản thân database” — vẫn là đặc điểm định hình phân biệt PostgreSQL với MySQL, Oracle, và SQL Server ngày nay, và đó cũng là lý do PostgreSQL có thể vừa là một engine quan hệ tuân thủ chuẩn nghiêm ngặt, vừa là nền tảng cho những thứ như lưu trữ document JSON đầy đủ hay tìm kiếm tương đồng vector, mà không cần rời khỏi cùng một hệ thống.

Bài viết này là điểm khởi đầu của roadmap PostgreSQL DBA: nó thiết lập nền tảng khái niệm (mô hình quan hệ, ACID, OLTP/OLAP) mà mọi chủ đề sau này — cài đặt, thiết kế schema, indexing, transaction, replication, bảo mật — đều xây dựng dựa trên đó.

Kiến thức nền tảng

Mô hình quan hệ, một cách chính thức

Mô hình quan hệ của Codd đặt tên chính xác, mang tính toán học cho những gì hầu hết mọi người đã hình dung là “một bảng”:

Thuật ngữ thông thườngThuật ngữ chính thứcĐịnh nghĩa
Bảng (table)Quan hệ (relation)Một tập hợp các tuple có tên, tất cả cùng chia sẻ chung các thuộc tính (cột)
Hàng / bản ghiTupleMột tập giá trị có thứ tự duy nhất, mỗi giá trị ứng với một thuộc tính, trong một quan hệ
Cột / trườngThuộc tính (attribute)Một thành phần có tên, có kiểu của tuple (ví dụ: email TEXT)
Cấu trúc bảngSchema (của quan hệ)Tập tên thuộc tính và miền giá trị (domain/type) của chúng
Miền giá trịDomainTập các giá trị hợp lệ mà một thuộc tính có thể nhận (ví dụ: INTEGER, BOOLEAN)

Hai đảm bảo sau xuất phát trực tiếp từ việc coi một quan hệ như một tập hợp (set) toán học của các tuple, và chúng có ý nghĩa thực tiễn, không chỉ là lý thuyết:

Các quan hệ kết nối với nhau thông qua khóa (key): một khóa chính (primary key) xác định duy nhất mỗi tuple trong chính quan hệ của nó, và một khóa ngoại (foreign key) trong một quan hệ tham chiếu đến khóa chính (hoặc khóa duy nhất) trong quan hệ khác, mã hóa một mối quan hệ mà không cần nhân bản dữ liệu. Đây là điều cho phép bạn tách orderscustomers thành các bảng riêng biệt mà vẫn có thể tái tạo lại “khách hàng nào đặt đơn hàng nào” — thông qua join — thay vì nhân bản dữ liệu khách hàng vào mọi hàng đơn hàng, và cho phép database thực thi tính toàn vẹn tham chiếu (referential integrity) (bạn không thể chèn một đơn hàng cho khách hàng không tồn tại) như một đảm bảo hạng nhất thay vì một quy ước ở tầng ứng dụng.

Lợi ích và hạn chế của RDBMS

Nền tảng toán học của mô hình quan hệ chuyển hóa thành những lợi ích kỹ thuật cụ thể, nhưng nó cũng tạo ra những ràng buộc thực sự — hiểu cả hai mặt là điều giúp một DBA lựa chọn (hoặc bảo vệ) PostgreSQL cho một workload cụ thể thay vì chọn nó chỉ vì thói quen.

Lợi íchHạn chế
Đảm bảo consistency mạnh mẽ thông qua transaction ACIDHorizontal scaling (sharding trên nhiều node) khó hơn so với các hệ NoSQL được xây dựng chuyên biệt cho việc đó
Ngôn ngữ truy vấn (SQL) trưởng thành, chuẩn hóa, khả chuyển giữa các hệ thống và kỹ năngThay đổi schema đòi hỏi migration tường minh; thêm một cột vào bảng khổng lồ có thể gây lock hoặc rewrite toàn bảng
Join khai báo (declarative), mạnh mẽ trên các bảng đã chuẩn hóaKhông phù hợp với dữ liệu ghi cực nhiều, ít cấu trúc (ví dụ: telemetry IoT thô, log phi cấu trúc ở quy mô khổng lồ)
Query optimizer khai báo giải phóng developer khỏi việc tự viết đường truy cập dữ liệuVertical scaling (máy lớn hơn) là con đường mở rộng mặc định trước khi sharding trở nên cần thiết
Hệ sinh thái phong phú: hàng chục năm công cụ, ORM, giám sát, DBA đã quen với mô hình nàyKiểu dữ liệu/ràng buộc chặt chẽ làm tăng chi phí thiết kế schema ban đầu so với các kho lưu trữ schema-on-read

Không hạn chế nào là chí mạng — chúng đều là đánh đổi. Một schema quan hệ được mô hình hóa tốt cùng index phù hợp sẽ vượt trội hơn một kho NoSQL được dùng một cách ngây thơ, đối với hầu hết ứng dụng transactional. Và bản thân PostgreSQL còn chủ động giảm nhẹ nhiều hạn chế kể trên (JSONB cho dữ liệu bán cấu trúc, logical replication và các extension như Citus cho horizontal scaling), đó là một phần lý do nó trở thành lựa chọn mặc định cho rất nhiều loại workload, thay vì chỉ là một RDBMS chuyên biệt hẹp.

Khái niệm chính

PostgreSQL so với các RDBMS khác

Mọi RDBMS lớn đều triển khai cùng một lõi quan hệ, nhưng chúng khác biệt rõ rệt về khả năng mở rộng, mức độ tuân thủ chuẩn, và kiến trúc concurrency — và những khác biệt đó thường mới là thứ thực sự quyết định bạn chọn hệ nào.

Khía cạnhPostgreSQLMySQLOracleSQL ServerSQLite
Giấy phép / chi phíMã nguồn mở, giấy phép PostgreSQL rất khoáng đạt (miễn phí)Mã nguồn mở (GPL) + gói Enterprise trả phíĐộc quyền, chi phí license đắt đỏĐộc quyền, license theo corePublic domain, nhúng (embedded), miễn phí
Khả năng mở rộngRất cao: kiểu dữ liệu tùy chỉnh, toán tử, index access method, ngôn ngữ thủ tục, extension (pgvector, PostGIS, TimescaleDB)Hạn chế; storage engine có thể thay (InnoDB, MyISAM) nhưng hệ thống kiểu là đóngCao nhưng độc quyền (package PL/SQL)Trung bình (tích hợp CLR, T-SQL)Tối thiểu; không nhắm đến việc mở rộng
Tuân thủ chuẩn SQLRất cao — bám sát chuẩn SQLTrước đây lỏng lẻo hơn (ép kiểu ngầm, cắt bớt giá trị âm thầm)Cao, kèm nhiều phần mở rộng độc quyềnCao, kèm phương ngữ mở rộng T-SQLMột phần; kiểu dữ liệu động đi lệch khỏi chuẩn
Mô hình concurrencyMVCC qua các phiên bản tuple trong heap + vacuumMVCC trong InnoDB (undo log, gần với cách tiếp cận của Oracle)MVCC qua undo segment/rollbackMặc định dựa trên lock, tùy chọn MVCC (snapshot isolation)Ghi đơn (single-writer), khóa ở mức file
Tùy chọn indexingB-tree, Hash, GiST, SP-GiST, GIN, BRIN — index access method có thể cắm thêmChủ yếu B-tree (+ full-text, spatial hạn chế)B-tree, bitmap, function-based, domain indexB-tree (clustered/non-clustered), columnstoreChỉ B-tree
Trường hợp dùng điển hìnhOLTP đa dụng, dữ liệu địa lý, JSON, analytics nhờ extensionỨng dụng web, workload nặng đọc, thiết lập ưu tiên đơn giảnDoanh nghiệp lớn, hệ thống legacy trọng yếuHệ sinh thái doanh nghiệp thiên về Windows/.NETNhúng, mobile, lưu trữ cục bộ một file

Hai điểm khác biệt đáng ghi nhớ nhất trong bảng trên là khả năng mở rộngcách hiện thực MVCC. Cơ chế extension của PostgreSQL (CREATE EXTENSION) cho phép bạn thêm những kiểu dữ liệu và phương thức index thực sự mới mà không cần fork database — đây chính là cách pgvector (tìm kiếm tương đồng vector) và PostGIS (dữ liệu địa lý) tồn tại như những công dân hạng nhất, thay vì các hack chắp vá thêm vào. Và thiết kế MVCC cụ thể của PostgreSQL — lưu nhiều phiên bản của một hàng ngay trong heap của bảng và dựa vào VACUUM để thu hồi các phiên bản đã chết — đánh đổi một chút overhead lưu trữ/bảo trì (bloat, nhu cầu vacuum) để lấy về một đường đọc đơn giản, không blocking, nơi reader không bao giờ chặn writer và writer không bao giờ chặn reader. Hãy so sánh điều này với mô hình lock mặc định của SQL Server, nơi truy cập đồng thời một cách ngây thơ có thể tạo ra chuỗi blocking mà Postgres, MySQL/InnoDB, hay Oracle sẽ không gặp phải.

PostgreSQL so với các database NoSQL

Ranh giới lịch sử “dùng Postgres cho dữ liệu quan hệ có cấu trúc, dùng kho NoSQL cho dữ liệu linh hoạt/quy mô khổng lồ” đã mờ đi khá nhiều, chủ yếu nhờ hai tính năng của PostgreSQL: JSONB, một kiểu cột JSON nhị phân, có thể index, cho phép bạn lưu và truy vấn các document linh hoạt về schema ngay bên trong một bảng quan hệ thông thường, và các extension như pgvector, biến PostgreSQL thành một vector database khả thi cho embedding và tìm kiếm tương đồng. Giờ đây hoàn toàn có thể chạy một workload kiểu document store, một workload full-text search, và một workload semantic search, tất cả trong cùng một instance PostgreSQL.

Tuy vậy, đánh đổi cơ bản được mô tả trong NoSQL Databases vẫn đúng, và JSONB không xóa bỏ nó — nó chỉ tạo ra một lối thoát bên trong một hệ thống quan hệ. Hãy chọn PostgreSQL (mô hình hóa quan hệ, kể cả khi có cột JSONB) khi:

Hãy chọn một kho NoSQL chuyên biệt thay vào đó khi:

Quy tắc thực tế mà hầu hết DBA đi đến: mặc định chọn PostgreSQL cho các workload transactional và đa dụng, và chỉ áp dụng một hệ NoSQL chuyên biệt khi có lý do cụ thể, đã được đo lường (một access pattern hay yêu cầu quy mô cụ thể mà Postgres không đáp ứng được), thay vì một cảm giác mơ hồ rằng “NoSQL scale tốt hơn”.

ACID, xem trước

Mọi transaction quan hệ mà PostgreSQL commit đều được kỳ vọng thỏa mãn ACID: Atomicity (Tính nguyên tử — mọi ghi trong một transaction xảy ra hết hoặc không xảy ra gì cả), Consistency (Tính nhất quán — một transaction đưa database từ trạng thái hợp lệ này sang trạng thái hợp lệ khác, tôn trọng các ràng buộc), Isolation (Tính cô lập — các transaction đồng thời không thấy trạng thái trung gian chưa commit của nhau), và Durability (Tính bền vững — một khi đã commit, dữ liệu sống sót qua sự cố crash). Cơ chế đầy đủ — isolation level, các loại anomaly, locking — được trình bày trong Backend — Relational Databases và sẽ được đào sâu ở Transactions & Concurrency Control; bài viết này chỉ xem trước cách PostgreSQL cụ thể hiện thực hai trong bốn chữ cái đó, vì nó giải thích rất nhiều hành vi đặc trưng của PostgreSQL sẽ gặp lại sau này trong roadmap:

OLTP so với OLAP so với HTAP

Không phải mọi workload database đều giống nhau, và hình dạng của workload nên quyết định schema, chiến lược indexing, thậm chí cả lựa chọn engine. Ba nhóm rộng sau mô tả phổ này:

Khía cạnhOLTPOLAPHTAP
Tên đầy đủOnline Transaction ProcessingOnline Analytical ProcessingHybrid Transactional/Analytical Processing
Truy vấn điển hìnhNgắn, đơn giản (tra cứu/cập nhật một hàng)Dài, phức tạp (aggregation trên hàng triệu hàng)Cả hai, trên cùng dữ liệu
Khối lượng truy vấnRất cao (hàng nghìn/giây)Thấp đến trung bìnhCao cho phần OLTP, trung bình cho phần analytics
Phạm vi dữ liệu mỗi truy vấnVài hàngQuét lớn, thường toàn bảng/partitionHỗn hợp
Bố cục lưu trữHướng hàng (row-oriented — nhanh khi đọc/ghi nguyên hàng)Hướng cột (column-oriented — nhanh khi quét ít cột trên nhiều hàng)Thường hỗn hợp hoặc bố cục kép
Hệ thống điển hìnhPostgreSQL, MySQL, Oracle (như engine OLTP)Snowflake, BigQuery, Redshift, ClickHouseTiDB, SingleStore, PostgreSQL + extension columnar (ví dụ: Citus, hydra/columnar)
Điểm mạnh truyền thống của PostgreSQLXuất sắc — đây chính là thế mạnh cốt lõi của PostgresYếu theo mặc định (lưu trữ theo hàng gây bất lợi cho quét rộng)Đang hình thành, thông qua extension

Storage engine của PostgreSQL về bản chất là hướng hàng (row-oriented), và chính điều đó khiến nó nhanh với OLTP: lấy hoặc cập nhật một hàng đầy đủ (một bản ghi khách hàng, một đơn hàng) chỉ chạm vào một khối liền kề trên đĩa. Nhưng cùng bố cục đó lại là bất lợi cho các truy vấn kiểu OLAP — SELECT AVG(amount) FROM orders chỉ cần một cột, nhưng row store vẫn phải đọc toàn bộ mỗi hàng vào bộ nhớ để lấy được cột đó. Đây là lý do các data warehouse cổ điển dùng lưu trữ hướng cột (column-oriented) thay vào đó: mỗi cột được lưu liền kề, nên quét một cột trên hàng tỷ hàng chỉ đọc dữ liệu của cột đó, và nén tốt hơn nhiều.

HTAP là nỗ lực mới nổi nhằm phục vụ cả hai pattern từ cùng một hệ thống mà không cần duy trì một pipeline ETL riêng biệt sang warehouse. PostgreSQL không hỗ trợ columnar storage nguyên bản, nhưng mô hình extension của nó khiến các thiết lập kiểu HTAP trở nên khả thi: các extension thêm bảng lưu trữ dạng columnar song song với các bảng row-based thông thường trong cùng database, để dữ liệu transactional “nóng” gần đây có thể vẫn ở dạng row-oriented trong khi dữ liệu lịch sử hoặc nặng về báo cáo sống ở định dạng columnar tối ưu cho aggregation — tất cả đều truy vấn được qua cùng giao diện SQL. Đây vẫn là một lĩnh vực còn non trẻ so với hàng chục năm trưởng thành về OLTP của Postgres, và hầu hết hệ thống production vẫn kết hợp PostgreSQL (OLTP) với một warehouse chuyên dụng (OLAP) được nạp dữ liệu qua change-data-capture hoặc batch ETL, nhưng đáng để biết HTAP tồn tại như một hướng đi mà hệ sinh thái đang tiến tới.

Best Practices

Bản đồ roadmap

Chủ đề này là điểm khởi đầu về mặt khái niệm; phần còn lại của roadmap sẽ mở rộng dần theo thứ tự đại khái sau:

Tài liệu tham khảo

Part of the PostgreSQL DBA Roadmap knowledge base.

Overview

A relational database management system (RDBMS) stores data as a collection of tables — grids of rows and columns — and lets you relate one table to another through shared key values instead of through pointers or physical nesting. You do not tell an RDBMS how to find the data (walk this pointer, then that one); you tell it what you want in a declarative language, SQL (Structured Query Language), and the database’s query planner figures out the fastest way to get it. This separation between “what” and “how” is the single biggest reason the relational model has dominated business-critical data storage for over fifty years: application code can change constantly, but the query planner can be rewritten, upgraded, and re-optimized without anyone touching a single SELECT statement.

This was not always how databases worked. Before Codd’s relational model (1970), the two dominant approaches were the hierarchical model (IBM’s IMS, 1966) — data organized as a strict tree, where every record has exactly one parent, mirroring a filesystem — and the network model (CODASYL, late 1960s) — a graph of records connected by explicit pointers, more flexible than a tree but still navigated by explicit pointer-chasing code. Both required the application programmer to know the physical layout of the data and to write imperative code that walked those physical links one record at a time. Reorganizing the physical structure — adding a new access path, changing a pointer chain — meant rewriting every program that touched it. Codd’s insight was to separate the logical structure of data (relations, defined by their columns and constraints) from its physical storage and access paths, and to let a query language express intent instead of navigation. That decoupling is why the relational model won: schemas could evolve, storage engines could be optimized, and indexes could be added — all without breaking the applications built on top, as long as the logical shape of the data (the schema) stayed compatible.

PostgreSQL is one implementation of this model — but a particularly ambitious one. It began as POSTGRES, a research project at UC Berkeley led by Michael Stonebraker (the same person behind Ingres, one of the earliest relational systems), explicitly designed to go beyond the relational model of the 1980s by supporting user-defined types, rules, and extensibility. When SQL support was added in 1995 the project was renamed Postgres95, and by 1996 it became PostgreSQL under its current open-source community governance. That research DNA — “let users extend the type system and the database itself” — is still the defining trait that separates PostgreSQL from MySQL, Oracle, and SQL Server today, and it is the reason PostgreSQL can serve as both a strict, standards-compliant relational engine and a platform for things like full JSON document storage or vector similarity search without leaving the same system.

This note is the starting point for the PostgreSQL DBA roadmap: it establishes the conceptual foundation (the relational model, ACID, OLTP/OLAP) that every later topic — installation, schema design, indexing, transactions, replication, security — builds on.

Fundamentals

The relational model, formally

Codd’s relational model gives precise, mathematical names to what most people already picture as “a table”:

Informal termFormal termDefinition
TableRelationA named set of tuples that all share the same attributes (columns)
Row / recordTupleA single, ordered set of values, one per attribute, within a relation
Column / fieldAttributeA named, typed component of a tuple (e.g., email TEXT)
Table structureSchema (of the relation)The set of attribute names and their domains (types)
DomainDomainThe set of legal values an attribute can take (e.g., INTEGER, BOOLEAN)

Two guarantees fall directly out of treating a relation as a mathematical set of tuples, and they matter in practice, not just in theory:

Relations connect to each other through keys: a primary key uniquely identifies each tuple in its own relation, and a foreign key in one relation references a primary (or unique) key in another, encoding a relationship without duplicating data. This is what lets you split orders and customers into separate tables and still reconstruct “which customer placed which order” — via a join — instead of duplicating customer data into every order row, and lets the database enforce referential integrity (you cannot insert an order for a customer that does not exist) as a first-class guarantee rather than an application-level convention.

RDBMS benefits and limitations

The relational model’s mathematical grounding translates into concrete engineering benefits, but it also creates real constraints — understanding both is what lets a DBA choose (or defend) PostgreSQL for a given workload instead of reaching for it out of habit.

BenefitsLimitations
Strong consistency guarantees via ACID transactionsHorizontal scaling (sharding across many nodes) is harder than in purpose-built distributed NoSQL systems
Mature, standardized query language (SQL) portable across systems and skill setsSchema changes require explicit migrations; adding a column to a huge table can lock or rewrite it
Powerful, declarative joins across normalized tablesNot ideal for extremely high-write, loosely-structured data (e.g., raw IoT telemetry, unstructured logs at massive scale)
Declarative query optimizer frees developers from hand-written access pathsVertical scaling (bigger machine) is the default scaling path before sharding becomes necessary
Rich ecosystem: decades of tooling, ORMs, monitoring, DBAs who know the modelRigid typing/constraints add upfront schema design cost compared to schema-on-read stores

None of the limitations are fatal — they are trade-offs. A well-modeled relational schema with the right indexes will outperform a naively-used NoSQL store for most transactional applications, and PostgreSQL specifically pushes back on several of these limitations (JSONB for semi-structured data, logical replication and extensions like Citus for horizontal scaling), which is part of why it has become the default choice across so many workload types rather than a narrow specialist RDBMS.

Key Concepts

PostgreSQL vs. other RDBMS

All major RDBMS implement the same relational core, but they diverge sharply on extensibility, standards adherence, and concurrency architecture — and those differences are usually what actually decides which one you pick.

AspectPostgreSQLMySQLOracleSQL ServerSQLite
License / costOpen source, permissive PostgreSQL License (no-cost)Open source (GPL) + paid Enterprise tierProprietary, expensive licensingProprietary, licensing per corePublic domain, embedded, free
ExtensibilityVery high: custom types, operators, index access methods, procedural languages, extensions (pgvector, PostGIS, TimescaleDB)Limited; storage engine pluggable (InnoDB, MyISAM) but type system is closedHigh but proprietary (PL/SQL packages)Moderate (CLR integration, T-SQL)Minimal; not meant to be extended
Standards complianceVery high — closely tracks SQL standardHistorically looser (implicit type coercion, silent truncation)High, with many proprietary extensionsHigh, with T-SQL dialect extensionsPartial; dynamic typing departs from the standard
Concurrency modelMVCC via tuple versions in the heap + vacuumMVCC in InnoDB (undo logs, closer to Oracle’s approach)MVCC via undo segments/rollbackLock-based by default, optional MVCC (snapshot isolation)Single-writer, file-level locking
Indexing optionsB-tree, Hash, GiST, SP-GiST, GIN, BRIN — pluggable index access methodsPrimarily B-tree (+ limited full-text, spatial)B-tree, bitmap, function-based, domain indexesB-tree (clustered/non-clustered), columnstoreB-tree only
Typical use caseGeneral purpose OLTP, geospatial, JSON workloads, analytics with extensionsWeb applications, read-heavy workloads, simplicity-first setupsLarge enterprise, legacy mission-critical systemsWindows/.NET-centric enterprise stacksEmbedded, mobile, single-file local storage

The two differentiators worth internalizing above the rest of the table are extensibility and MVCC implementation. PostgreSQL’s extension framework (CREATE EXTENSION) lets you add genuinely new data types and index methods without forking the database — this is how pgvector (vector similarity search) and PostGIS (geospatial data) exist as first-class citizens rather than bolted-on hacks. And PostgreSQL’s specific MVCC design — storing multiple row versions directly in the table heap and relying on VACUUM to reclaim dead versions — trades some storage/maintenance overhead (bloat, the need to vacuum) for a simpler, non-blocking read path where readers never block writers and writers never block readers. Contrast this with SQL Server’s default locking model, where naive concurrent access can produce blocking chains that Postgres, MySQL/InnoDB, or Oracle would not.

PostgreSQL vs. NoSQL databases

The historical line between “use Postgres for structured relational data, use a NoSQL store for flexible/huge-scale data” has blurred considerably, mostly because of two PostgreSQL features: JSONB, a binary, indexable JSON column type that lets you store and query schema-flexible documents inside a normal relational table, and extensions like pgvector, which turns PostgreSQL into a viable vector database for embeddings and similarity search. It is now genuinely possible to run a document-store-like workload, a full-text search workload, and a semantic-search workload all inside one PostgreSQL instance.

That said, the fundamental trade-off described in NoSQL Databases still holds, and JSONB does not erase it — it just gives you an escape hatch within a relational system. Reach for PostgreSQL (relational modeling, even with JSONB columns) when:

Reach for a purpose-built NoSQL store instead when:

The practical rule most DBAs converge on: default to PostgreSQL for transactional and general-purpose workloads, and adopt a specialized NoSQL system only once you have a concrete, measured reason (a specific access pattern or scale requirement Postgres cannot meet) rather than a vague sense that “NoSQL is more scalable.”

ACID, previewed

Every relational transaction that PostgreSQL commits is expected to satisfy ACID: Atomicity (a transaction’s writes all happen or none do), Consistency (a transaction moves the database from one valid state to another, respecting constraints), Isolation (concurrent transactions do not see each other’s uncommitted intermediate state), and Durability (once committed, data survives a crash). The full mechanics — isolation levels, anomalies, locking — are covered in Backend — Relational Databases and will be revisited in depth in Transactions & Concurrency Control; this note only previews how PostgreSQL specifically delivers on two of the four letters, because it explains a lot of PostgreSQL’s distinctive behavior later in the roadmap:

OLTP vs. OLAP vs. HTAP

Not all database workloads look alike, and the shape of the workload should drive schema, indexing, and even engine choice. Three broad categories describe the spectrum:

AspectOLTPOLAPHTAP
Full nameOnline Transaction ProcessingOnline Analytical ProcessingHybrid Transactional/Analytical Processing
Typical queryShort, simple (single-row lookups/updates)Long, complex (aggregations across millions of rows)Both, on the same data
Query volumeVery high (thousands/sec)Low to moderateHigh for OLTP-style, moderate for analytics
Data scope per queryA few rowsLarge scans, often whole tables/partitionsMixed
Storage layoutRow-oriented (fast for whole-row read/write)Column-oriented (fast for scanning few columns across many rows)Often mixed or dual-layout
Typical systemsPostgreSQL, MySQL, Oracle (as OLTP engines)Snowflake, BigQuery, Redshift, ClickHouseTiDB, SingleStore, PostgreSQL + columnar extensions (e.g., Citus, hydra/columnar)
PostgreSQL’s traditional fitExcellent — this is Postgres’s core strengthWeak by default (row storage penalizes wide scans)Emerging, via extensions

PostgreSQL’s storage engine is fundamentally row-oriented, which is precisely what makes it fast at OLTP: fetching or updating one full row (a customer record, an order) touches one contiguous chunk of disk. That same layout is a liability for OLAP-style queries — SELECT AVG(amount) FROM orders only needs one column but a row store still has to read every full row into memory to get at it. This is why classic data warehouses use column-oriented storage instead: each column is stored contiguously, so scanning one column across a billion rows reads only that column’s data and compresses far better besides.

HTAP is the emerging attempt to serve both patterns from the same system without maintaining a separate ETL pipeline into a warehouse. PostgreSQL does not natively provide columnar storage, but its extension model makes HTAP-style setups possible: extensions add columnar table storage alongside normal row-based tables in the same database, so recent “hot” transactional data can stay row-oriented while historical or reporting-heavy data lives in a columnar format optimized for aggregation — all queryable through the same SQL interface. This is still a young area compared to Postgres’s decades of OLTP maturity, and most production systems still pair PostgreSQL (OLTP) with a dedicated warehouse (OLAP) fed by change-data-capture or batch ETL, but it is worth knowing HTAP exists as the direction the ecosystem is moving.

Best Practices

Map of the roadmap

This topic is the conceptual entry point; the rest of the roadmap builds outward from here in roughly this order:

References