โหมดมืด
บทที่ 0 — Database คืออะไร และทำไมต้องมี
1. ปัญหาก่อนมี Database
ลองคิดดู — ถ้าเราจะเก็บข้อมูล user 1 ล้านคน:
วิธี 1: ไฟล์ text
users.txt:
1,anna@example.com,Anna,25
2,ben@example.com,Ben,30
3,carol@example.com,Carol,28
...ปัญหา:
- หา user คนหนึ่ง → อ่านไฟล์ทั้งไฟล์ (ช้า)
- 2 คน edit พร้อมกัน → ทับกัน
- ไฟล์พัง → ข้อมูลหายหมด
- ไม่มี structure ที่บังคับ (insert "abc,xyz" ก็ได้)
- ทำ join กับไฟล์อื่นยาก
- ไม่มี backup เป็นระบบ
วิธี 2: JSON file
json
[
{"id": 1, "email": "anna@example.com", "name": "Anna", "age": 25},
...
]ยังเจอปัญหาเหมือนเดิม
Database = software ที่ออกแบบมาแก้ปัญหาเหล่านี้ทั้งหมด:
- ✅ เก็บ + ค้น data ได้เร็วแม้มีหลายร้อยล้านแถว
- ✅ หลายคนใช้พร้อมกันได้ (concurrency (คอน-เคอ-เรน-ซี) = การทำงานพร้อมกันหลายคน/หลายงาน)
- ✅ Crash → ข้อมูลไม่หาย (durability = ความคงทน — COMMIT แล้วข้อมูลอยู่ถาวรแม้ไฟดับ/เครื่องพัง)
- ✅ บังคับ structure (schema)
- ✅ Join data หลายตาราง
- ✅ Backup, replication, security
2. ประเภท Database
A. Relational (SQL) Database — RDBMS
- เก็บเป็น table ที่มี row + column
- ใช้ SQL (Structured Query Language)
- มี schema บังคับ (column ไหนเก็บอะไร)
- มี relation ระหว่าง table
ตัวอย่าง: PostgreSQL, MySQL, SQL Server, Oracle, SQLite
B. NoSQL Database
| ประเภท | เก็บยังไง (อธิบายง่าย) | ตัวอย่าง | ใช้เมื่อ |
|---|---|---|---|
| Document | เก็บข้อมูลเป็นก้อน JSON 1 ก้อนต่อ 1 record | MongoDB, CouchDB | schema ยืดหยุ่น, nested data |
| Key-Value | จับคู่ key → value เหมือน dictionary | Redis, DynamoDB | cache, session, queue |
| Column-family | เก็บแยกเป็น column ทำให้เขียน/อ่าน column ใหญ่ ๆ เร็ว | Cassandra (แคส-ซาน-ดร้า), HBase (เอช-เบส) | write-heavy, time series |
| Graph | เก็บเป็นจุด (node) + เส้นเชื่อม (edge) | Neo4j (นี-โอ-โฟร์-เจ), Dgraph | social network, recommendation |
| Time-series | optimize เฉพาะข้อมูลที่มี timestamp (IoT, log, metric) | TimescaleDB, InfluxDB v3, QuestDB | IoT, observability, monitoring |
| Vector | เก็บ vector ที่ AI แปลงข้อความ/รูปเป็นตัวเลข เพื่อค้น "ความหมาย" | Pinecone, Qdrant (คิว-ดรานท์), Milvus, Weaviate, Turbopuffer, pgvector | AI search, RAG (Retrieval-Augmented Generation — ระบบ AI ที่ค้นข้อมูลก่อนตอบ) |
3. SQL vs NoSQL — เลือกยังไง
| SQL | NoSQL | |
|---|---|---|
| Structure | rigid schema | flexible |
| Relation | ดี (JOIN) | จำกัด |
| Scale | vertical (ดูหมายเหตุด้านล่าง) | horizontal |
| ACID | strong | eventual consistency (มัก) |
| Use case | banking, e-commerce, CRM (Customer Relationship Management — ระบบจัดการลูกค้า) | social feed, log, cache |
| Query language | SQL (standard) | ต่างกันทุกตัว |
📖 คำศัพท์ในตาราง — แยกศัพท์กับคำอธิบายให้อ่านง่าย:
- vertical scale (เวอร์-ทิ-คอล สเกล) = ขยายแนวตั้ง — เพิ่มสเปกเครื่องเดิม CPU/RAM ให้ใหญ่ขึ้น
- horizontal scale (ฮอ-ริ-ซอน-ทอล สเกล) = ขยายแนวนอน — เพิ่มจำนวนเครื่อง/server
- ACID (แอซิด) = 4 คุณสมบัติของ transaction (บทที่ 5 จะอธิบาย)
- eventual consistency (อี-เวน-ชวล คอน-ซิส-เทน-ซี) = "สุดท้ายข้อมูลจะตรงกัน" แต่ช่วงสั้น ๆ หลังเขียน แต่ละ server อาจเห็นค่าไม่ตรงกันชั่วคราว
- sharding (ชาร์-ดิ้ง) = แบ่ง data ออกเป็นชิ้น ๆ ไปเก็บคนละ server
- replication (เรพ-ลิ-เค-ชัน) = สำเนาข้อมูลข้าม server เพื่อกระจายโหลด/กัน data หาย
🟡 หมายเหตุเรื่อง scale (2026): ตาราง "SQL = vertical, NoSQL = horizontal" เป็นภาพแบบดั้งเดิมของ single-node SQL ปัจจุบันมี distributed SQL ที่ทำ horizontal scale ได้ (มี sharding/replication built-in) — ตัวอย่าง:
- Amazon Aurora (ออ-โร-ร่า) — managed PostgreSQL/MySQL บน AWS
- Citus (ไซ-ตัส) — extension ของ Postgres ทำ sharding
- CockroachDB (ค็อก-โรช-ดี-บี) — Postgres-compatible distributed SQL
- Google Spanner (สแปน-เนอร์) — distributed SQL ของ Google
- YugabyteDB (ยู-กา-ไบต์-ดี-บี) — Postgres-compatible distributed SQL
- Vitess (วิ-เทส) — sharding สำหรับ MySQL เท่านั้น (ไม่ใช่ Postgres — ใช้ใน YouTube, Slack)
ดังนั้นข้อจำกัดเรื่อง scale ของ SQL ในปี 2026 ไม่ได้แข็งเหมือนสมัยก่อน (last reviewed: 2026-06)
กฎทอง สำหรับมือใหม่:
- เริ่มด้วย SQL (PostgreSQL) — 95% ของ app ใช้ได้
- ใช้ NoSQL เมื่อมี use case ชัดเจน:
- Cache → Redis
- Search → Elasticsearch
- Real-time chat / feed → MongoDB
- AI embedding (เอ็ม-เบด-ดิ้ง — vector ที่ AI แปลงข้อความเป็นตัวเลข เพื่อค้นความหมาย) → pgvector (พี-จี-เวก-เตอร์ — extension ของ Postgres, extension = plugin เสริมความสามารถของ Postgres) หรือ Qdrant
"Pick boring technology" — Dan McKinley (แปล: "เลือกเทคโนโลยีที่น่าเบื่อ" — ในที่นี้ "boring" ไม่ได้แปลว่าน่าเบื่อในแง่ลบ แต่หมายถึง "ของที่นิ่ง พิสูจน์แล้ว ไม่มี surprise" — ตรงข้ามกับเทคโนโลยีใหม่ที่ตื่นเต้นแต่ยังมีบั๊ก) PostgreSQL "boring" แต่ปลอดภัย + flexible + รองรับ JSON ถ้าต้องการ
4. RDBMS Landscape — เลือกตัวไหน?
| จุดเด่น | จุดอ่อน | License | |
|---|---|---|---|
| PostgreSQL ⭐ | feature เยอะที่สุด (JSONB, GIS, full-text), open-source, รองรับ extension | learning curve สูงเล็กน้อย | free |
| MySQL | popularity สูง, replication ง่าย | bug + edge case แปลก ๆ | free (Oracle ดูแล) |
| MariaDB | fork ของ MySQL — community-driven | ecosystem/tooling รอบ Oracle MySQL ยังใหญ่กว่า | free |
| SQLite | embedded, ไม่ต้อง server, ไฟล์เดียว | ไม่ scalable, ไม่ multi-user | free |
| SQL Server | enterprise + Windows + integration ดี | paid, lock-in MS | paid |
| Oracle DB | enterprise + feature ครบ | paid + แพง + ซับซ้อน | paid |
ปี 2026 มือใหม่: ใช้ PostgreSQL ครับ — ฟรี + features ครบ + community ใหญ่
📌 Version stamp: ตัวอย่าง SQL ในเล่มนี้ใช้ PostgreSQL 17 เป็นหลัก (Docker image
postgres:17-alpine— GA กันยายน 2024) feature ส่วนใหญ่ทำงานได้ตั้งแต่ PG 15 ขึ้นไป (PG 14 EOL พฤศจิกายน 2026; PG 16 ยัง supported) — ก่อนนำไปใช้บน production แนะนำตรวจ release notes ของ Postgres เพื่อยืนยัน syntax/behavior ตาม minor version ที่คุณใช้สำหรับ MySQL หนังสือเล่มนี้อ้างอิง MySQL 8.4 LTS (เมษายน 2024) — MySQL 8.0 EOL เมษายน 2026 (last reviewed: 2026-06)
5. คำศัพท์พื้นฐาน
🔑 ก่อนเริ่ม — ในศัพท์ DB คำว่า "key" ไม่ใช่แค่ "ชื่อ column" (อย่างที่ Excel เรียก) แต่หมายถึง column ที่ทำหน้าที่พิเศษ — ระบุตัวตน ของ row (Primary Key) หรือ ชี้ไปแถวอื่น (Foreign Key)
| คำ | คำอ่าน | ความหมาย |
|---|---|---|
| Database | เด-ต้า-เบส | container ที่เก็บ table หลาย ๆ ตาราง |
| Table | เท-เบิล | "ตาราง" ใน excel — row + column |
| Row / Record | โรว / เร็ค-คอร์ด | 1 แถว = 1 entity (1 user, 1 order) |
| Column / Field | คอ-ลัมน์ / ฟิลด์ | 1 attribute (email, name, age) |
| Primary Key | ไพร-มา-รี คีย์ | column ที่ระบุตัวตน 1 row (ไม่ซ้ำ, ไม่ null) |
| Foreign Key | ฟอ-เริน คีย์ | column ที่ชี้ไปยัง Primary Key ของ table อื่น |
| Index | อิน-เด็กซ์ | data structure ช่วย lookup เร็ว (เหมือน index หนังสือ) |
| Query | คิว-เออ-รี | คำสั่ง SQL ที่เราเขียน |
| Schema | สคี-ม่า | "โครงสร้าง" ของ database (table + column + type) |
| Transaction | ทราน-แซก-ชัน | กลุ่มคำสั่งที่ทำสำเร็จร่วมกัน หรือ rollback ทั้งหมด |
| DDL | ดี-ดี-แอล | Data Definition Language — CREATE/ALTER/DROP |
| DML | ดี-เอ็ม-แอล | Data Manipulation Language — SELECT/INSERT/UPDATE/DELETE |
6. ตัวอย่าง — โครงสร้าง Table
table: users
┌────┬───────────────────┬───────┬─────┬─────────────────────┐
│ id │ email │ name │ age │ created_at │
├────┼───────────────────┼───────┼─────┼─────────────────────┤
│ 1 │ anna@example.com │ Anna │ 25 │ 2026-01-15 10:00:00 │
│ 2 │ ben@example.com │ Ben │ 30 │ 2026-01-16 14:30:00 │
│ 3 │ carol@example.com │ Carol │ 28 │ 2026-02-01 09:15:00 │
└────┴───────────────────┴───────┴─────┴─────────────────────┘
▲
│
Primary Key (unique, ไม่ซ้ำ, ไม่ null)table: orders
┌────┬─────────┬────────┬─────────────────────┐
│ id │ user_id │ total │ created_at │
├────┼─────────┼────────┼─────────────────────┤
│ 10 │ 1 │ 99.50 │ 2026-02-10 11:00:00 │
│ 11 │ 1 │ 250.00 │ 2026-02-15 16:20:00 │
│ 12 │ 2 │ 50.00 │ 2026-03-01 10:00:00 │
└────┴─────────┴────────┴─────────────────────┘
▲
│
Foreign Key → users.id→ user_id ใน orders อ้างถึง id ใน users = "order นี้เป็นของ user คนไหน"
7. PostgreSQL — Setup
ก่อนจะเขียน SQL ต้องมี database ให้เล่นก่อน — หนังสือนี้ใช้ PostgreSQL ติดตั้งได้ 2 ทาง: Docker (แนะนำสำหรับ dev เพราะลบ/สร้างใหม่ง่าย ไม่รก OS) หรือ install ตรงบน OS เลือกทางที่สะดวก แล้วทุกตัวอย่างในเล่มจะรันตามได้:
Option A: Docker (recommended สำหรับ dev)
⚠️ ก่อนรัน — ถ้ายังไม่รู้จัก Docker ให้ข้ามไป Option B ก่อน (Docker เป็นเครื่องมือรัน software ในกล่องเล็ก ๆ ที่เรียกว่า container แยกจาก OS — เหมาะกับ dev เพราะลบ/สร้างใหม่ง่าย ไม่รก OS) ถ้าจะใช้ Option A ต้องติดตั้ง Docker Desktop ก่อน → docker.com/products/docker-desktop
yaml
# docker-compose.yml
services: # services = list ของ container ที่จะรัน
db: # ชื่อ service (ใช้เรียกจาก container อื่น)
image: postgres:17-alpine # image = template ที่จะรัน (postgres 17 ตัวเล็ก alpine)
environment: # environment variable ที่ส่งให้ container
POSTGRES_DB: learning # ชื่อ database ที่จะสร้าง
POSTGRES_USER: dev # ชื่อ user
POSTGRES_PASSWORD: secret # ⚠️ DEV ONLY — production ห้ามใช้ password อ่อนแบบนี้
ports: # ports = แมป port ของ container → port ของเครื่อง
- "5432:5432" # "เครื่อง:container" — 5432 คือ port มาตรฐาน Postgres
volumes: # volumes = พื้นที่เก็บ data ถาวร (ไม่หายตอน restart)
- pgdata:/var/lib/postgresql/data # ชื่อ volume : path ใน container
volumes:
pgdata: # ประกาศ named volume ให้ Docker จัดการbash
docker compose up -d # -d = ทำงานเบื้องหลัง (detached)⚠️ Production: password
secretในตัวอย่างเป็น dev-only — production ต้องใช้ secret manager (AWS Secrets Manager, Vault, ฯลฯ) อย่า hard-code password ใน docker-compose ที่ commit ขึ้น git
Option B: Install บน OS
- macOS:
brew install postgresql@17 - Windows: installer ที่ postgresql.org
- Linux (Debian/Ubuntu):
sudo apt install postgresql-17— ⚠️ default apt repo อาจมีแค่ version เก่ากว่า ต้องตั้ง PGDG apt repo ก่อน → ดู postgresql.org/download/linux
8. GUI Tool — เลือก 1 ตัว
| Tool | ฟรี? | ระบบ |
|---|---|---|
| DBeaver ⭐ | ฟรี (Community) | Mac/Win/Linux — รองรับ DB หลายตัว |
| pgAdmin | ฟรี | Postgres เท่านั้น |
| DataGrip | paid | JetBrains — ดีที่สุดถ้าจ่ายได้ |
| TablePlus | ฟรี (limited) | Mac/Win — UI สวย |
ใช้ DBeaver ในหนังสือนี้ — ขั้นตอน connect ครั้งแรก:
- เปิด DBeaver → คลิกเมนู Database > New Database Connection (หรือกดไอคอน "+" ที่มุมบนซ้าย)
- เลือก PostgreSQL → คลิก Next
- กรอกข้อมูลในแท็บ Main:
- Host:
localhost - Port:
5432 - Database:
learning - Username:
dev - Password:
secret
- Host:
- คลิก Test Connection — ถ้าขึ้น "Connected" แสดงว่า OK → คลิก Finish
(ครั้งแรก DBeaver อาจถามให้ดาวน์โหลด JDBC driver ของ PostgreSQL — กด Download รอสักครู่)
9. CLI — psql
นอกจาก GUI แล้ว PostgreSQL มี CLI ชื่อ psql ที่ควรใช้เป็น — เร็วกว่าตอนทำงานบนเซิร์ฟเวอร์ที่ไม่มี GUI และมีคำสั่ง backslash (เครื่องหมาย \ — แบ็คสแลช, อยู่บนคีย์บอร์ดเหนือปุ่ม Enter) เช่น \dt, \d, \l สำหรับสำรวจ schema ส่วนนี้รวมคำสั่งที่ใช้บ่อย:
bash
# เข้าผ่าน docker
docker compose exec db psql -U dev -d learning
# หรือถ้า install บน host
psql -U dev -d learning
# คำสั่งใน psql
\dt # list tables
\d users # describe table
\l # list databases
\c learning # connect to database
\q # quit10. Hello, Database!
ลองครบวงจรแรกกัน — สร้าง table, เพิ่มข้อมูล, แล้ว query ออกมา เพื่อให้เห็นว่า database ทำงานยังไงตั้งแต่ต้นจนจบในไม่กี่บรรทัด ก่อนจะลงรายละเอียดแต่ละคำสั่งในบทถัด ๆ ไป:
💡 อย่ากังวลกับ keyword พวก
SERIAL,VARCHAR,UNIQUE,NOT NULL,TIMESTAMP,DEFAULT NOW()— บทที่ 1 จะอธิบายทุกตัว ที่นี่แค่อยากให้เห็นภาพรวม โค้ดสรุปสั้น ๆ:
SERIAL= เลขที่ DB นับเองอัตโนมัติ 1, 2, 3, ... (รุ่นใหม่แนะนำใช้GENERATED ALWAYS AS IDENTITYแทน — บทที่ 1)VARCHAR(255)= string ยาวไม่เกิน 255 ตัวอักษรUNIQUE= ห้ามซ้ำในตารางNOT NULL= ห้ามเป็นค่าว่างINTEGER= ตัวเลขจำนวนเต็มTIMESTAMP DEFAULT NOW()= เวลาปัจจุบัน ถ้าไม่ใส่ค่าเอง
sql
-- สร้าง table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(100) NOT NULL,
age INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
-- เพิ่มข้อมูล
INSERT INTO users (email, name, age) VALUES
('anna@example.com', 'Anna', 25),
('ben@example.com', 'Ben', 30);
-- ดึงข้อมูล
SELECT * FROM users;
-- ผลลัพธ์:
-- id │ email │ name │ age │ created_at
-- ────┼───────────────────┼──────┼─────┼─────────────────────
-- 1 │ anna@example.com │ Anna │ 25 │ 2026-05-18 10:00:00
-- 2 │ ben@example.com │ Ben │ 30 │ 2026-05-18 10:00:00ทำได้ → พร้อมเริ่มบทถัดไป
11. Mental Model ที่จะใช้ตลอดเล่ม
ทุกครั้งที่เขียน query — คิดว่า:
- What table? — query ตัวไหน
- What rows? — filter ด้วย WHERE
- What columns? — select column ไหนบ้าง
- In what order? — ORDER BY
- How many? — LIMIT
sql
SELECT name, email -- 3. column
FROM users -- 1. table
WHERE age > 18 -- 2. filter
ORDER BY created_at DESC -- 4. order
LIMIT 10; -- 5. countDatabase ทำงานในลำดับ:
FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT💡 อ่านผ่าน ๆ ก่อน —
GROUP BY,HAVING,DISTINCTยังไม่ได้สอน — บทถัดไป (1) จะอธิบาย DISTINCT บทที่ 3 จะอธิบาย GROUP BY/HAVING ที่นี่แค่อยากให้รู้ว่า "DB รันคำสั่งตามลำดับนี้ ไม่ใช่ตามที่เราเขียน"
SELECT ไม่ใช่ขั้นตอนแรก! — DB รัน WHERE ก่อน SELECT ลำดับเหตุการณ์เป็นแบบนี้:
WHEREทำงานก่อนSELECT- ตอนนั้น alias (ชื่อเล่นที่ตั้งใน SELECT ด้วย
AS) ยังไม่ถูกสร้าง - จึงใช้ alias ใน
WHEREไม่ได้
sql
-- ❌ error: WHERE ทำงานก่อน SELECT → ไม่รู้จัก "age_next"
SELECT age + 1 AS age_next FROM users WHERE age_next > 20;
-- ✅ ถูก: เขียน expression เต็มใน WHERE
SELECT age + 1 AS age_next FROM users WHERE age + 1 > 20;12. Checkpoint
🛠️ Checkpoint 0.1 — Setup
ติดตั้ง PostgreSQL + DBeaver → connect ได้ → รัน SELECT version(); → เห็น version
🛠️ Checkpoint 0.2 — First Table
สร้าง table books:
- id (Primary Key, auto increment)
- title (String, required)
- author (String, required)
- published_year (Integer)
- created_at (Timestamp, default now)
Insert 5 row → SELECT ทั้งหมด → ลบ 1 row → ดูอีกที
13. สรุปบท
✅ Database = software ที่จัดการข้อมูลให้ปลอดภัย + เร็ว + concurrent
✅ SQL (PostgreSQL/MySQL) vs NoSQL (MongoDB/Redis) — ใช้ต่างกัน
✅ มือใหม่ → เริ่มด้วย PostgreSQL — boring but reliable
✅ Table = row + column, มี Primary Key + Foreign Key
✅ Database ทำงานในลำดับ: FROM → WHERE → GROUP → HAVING → SELECT → ORDER → LIMIT
✅ Setup: Docker (postgres:17-alpine) + DBeaver
🔤 Glossary · 📋 Style guide · 📅 last_verified: 2026-06-03