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