ข้ามไปยังเนื้อหา

PostgreSQL ขั้นสูง

มาถึงตอนนี้คุณสร้าง table ได้ เขียนคำสั่ง CRUD ได้ join row ที่เกี่ยวข้องกันได้ และเข้าใจเรื่อง index แล้ว นั่นคือแกนหลักเชิงสัมพันธ์ (relational core) และสำหรับหลายแอปพลิเคชันแค่นี้ก็เพียงพอ แต่ PostgreSQL ยังมาพร้อมกับฟีเจอร์อีกชั้นหนึ่งอย่างเงียบ ๆ ที่ทำให้ฐานข้อมูลเดียวสามารถทำงานที่คนมักจะหาบริการเสริมมาจัดการได้ ไม่ว่าจะเป็นการเก็บเอกสารที่ยืดหยุ่น การค้นหาข้อความภาษาธรรมชาติ การแคชผลลัพธ์ของ query ที่มีต้นทุนสูง และการรันตรรกะภายในตัว server เอง

โมดูลนี้คือทัวร์ของฟีเจอร์ชั้นที่สองนั้น ไม่มีอะไรในนี้มาแทนที่สิ่งที่คุณรู้อยู่แล้ว ทุกอย่างวางอยู่บน table, column และ query ธรรมดาที่คุณคุ้นอยู่แล้ว เป้าหมายคือให้คุณรู้จักสังเกตว่าเมื่อใดที่ฟีเจอร์ในตัวของ PostgreSQL จะช่วยให้คุณไม่ต้องไปต่อชิ้นส่วนเพิ่มเติมเข้ามา

table ธรรมดาเก็บ column ที่ตายตัวด้วยชนิดข้อมูลที่ตายตัว ฟีเจอร์ในโมดูลนี้ขยายภาพนั้นออกไปสี่ทิศทาง โดยทั้งหมดไม่ต้องออกไปจากฐานข้อมูล

flowchart TD
  T[(Ordinary tables)] --> J[JSONB columns: flexible documents]
  T --> F[Full-text search: rank natural language]
  T --> V[Views and materialized views: reusable and cached queries]
  T --> L[Functions and triggers: logic inside the server]
  J --> P[One database, many jobs]
  F --> P
  V --> P
  L --> P
สี่วิธีที่ Postgres ขยายขีดความสามารถของ table ธรรมดา

แต่ละกิ่งตอบโจทย์ในโลกจริงคนละแบบ column jsonb ทำให้ row เดียวเก็บเอกสารซ้อนกัน (nested document) ที่รูปร่างต่างกันในแต่ละ row ได้ ส่วน full-text search เปลี่ยนข้อความยาว ๆ ให้ค้นหาตามความหมายได้ แทนที่จะเทียบ substring แบบเป๊ะ ๆ ด้าน view ก็ตั้งชื่อให้ query ที่ซับซ้อน และ materialized view ยังจดจำผลลัพธ์ไว้ให้ด้วย สุดท้าย function และ trigger ย้ายตรรกะชิ้นเล็ก ๆ มาอยู่ติดกับข้อมูล เพื่อให้ทำงานสม่ำเสมอไม่ว่าแอปพลิเคชันไหนจะมาแตะ table นั้น

ถ้าเห็นในพริบตาว่าแต่ละฟีเจอร์แก้ปัญหาอะไรและมีต้นทุนอะไร ก็จะเลือกใช้ได้ง่ายขึ้นมาก

Featureแก้ปัญหาข้อแลกเปลี่ยนหลัก
jsonb columnsข้อมูลที่ยืดหยุ่น ซ้อนกัน และมี schema เบาการรับประกันชนิดข้อมูลอ่อนกว่า column จริง
Full-text searchค้นหาแบบจัดอันดับบนภาษาธรรมชาติต้องตั้งค่า language configuration ให้ถูก
Viewsตั้งชื่อและนำ query ที่ซับซ้อนมาใช้ซ้ำคำนวณใหม่ทุกครั้งที่อ่าน
Materialized viewsแคชผลลัพธ์ของ query ที่มีต้นทุนสูงผลลัพธ์ล้าสมัยจนกว่าจะ refresh
Functions and triggersตรรกะฝั่ง server ที่รันเสมอพฤติกรรมที่ซ่อนอยู่ซึ่งต้องบันทึกเอกสารไว้
  • JSONB — เก็บเอกสารที่ยืดหยุ่นไว้ใน column เข้าถึงข้างในด้วย operator อย่าง -> และ ->> แก้ไขด้วย jsonb_set และเร่งความเร็ว containment query ด้วย GIN index
  • Full-text search — เปลี่ยนข้อความให้เป็น tsvector จับคู่กับ tsquery ด้วย operator @@ จัดอันดับผลลัพธ์ด้วย ts_rank และทำ index เพื่อความเร็ว
  • Views และ materialized views — ตั้งชื่อให้ query ด้วย CREATE VIEW หรือแคชผลลัพธ์ไว้ด้วย CREATE MATERIALIZED VIEW แล้ว refresh เมื่อต้องการ
  • Functions และ triggers — เขียน PL/pgSQL function เล็ก ๆ ที่คืนค่า แล้วต่อ trigger เพื่อให้ function รันเองอัตโนมัติเมื่อมี INSERT หรือ UPDATE
  • หยิบฟีเจอร์เหล่านี้มาใช้เมื่อจำเป็นจริง ไม่ใช่เพราะมีให้ใช้ ถ้ารูปร่างของข้อมูลรู้แน่และคงที่ column ธรรมดายังดีกว่าฟิลด์ jsonb เสมอ
  • ชั้นนี้ส่วนใหญ่ก็ยังเป็น SQL อยู่ดี คุณจะยังเขียน SELECT, INSERT และ WHERE ต่อไป — ชิ้นส่วนใหม่ ๆ เพียงแค่เสียบเข้าไปในคำสั่งที่คุณเข้าใจอยู่แล้ว
  • ทุกฟีเจอร์ขั้นสูงล้วนมีเรื่องราวของ index ในตัว การรู้ว่าเมื่อใดควรเพิ่ม GIN index มักเป็นเส้นแบ่งระหว่างฟีเจอร์ที่ scale ได้กับฟีเจอร์ที่คลานต้วมเตี้ยม
  • ตรรกะที่อยู่ในฐานข้อมูลนั้นทรงพลังแต่ลืมง่าย จงบันทึกเอกสารของทุก view, function หรือ trigger เพื่อให้คนต่อไปรู้ว่ามีของพวกนี้อยู่
ฟีเจอร์ใดของ PostgreSQL เหมาะที่สุดสำหรับเก็บเอกสารที่ยืดหยุ่นและซ้อนกัน ซึ่งรูปร่างต่างกันได้ในแต่ละ row?
ข้อแลกเปลี่ยนหลักของ materialized view เมื่อเทียบกับ view ธรรมดาคืออะไร?
แก่นร่วมของทุกฟีเจอร์ในโมดูลนี้คืออะไร?