ฐานข้อมูล
หน้านี้สอนอะไร
SQLite, Turso, Postgres และ PGlite: การเชื่อมต่อ การเลือก และการปรับแต่ง
ควรอ่านก่อน: เริ่มใช้งาน
SQLite
npm install @easy-cms/db-sqlitepnpm add @easy-cms/db-sqliteyarn add @easy-cms/db-sqlitebun add @easy-cms/db-sqliteimport { sqlite } from '@easy-cms/db-sqlite'
db: sqlite({ url: 'file:./cms.db' }) // relative to the project root
db: sqlite({ url: 'libsql://my-db.turso.io', authToken: process.env.TURSO_TOKEN })ใช้ libSQL ไม่รองรับฐานข้อมูลแบบ in-memory (:memory:)
SQLite เขียนได้ทีละรายการ การเขียนใน process เดียวกันจะเข้าคิวรอกัน ส่วนเมื่อ process อื่นเขียนไฟล์เดียวกันอยู่ (server ตัวที่สอง หรือคำสั่ง easy-cms) การเขียนจะรอได้นานสูงสุด busyTimeout (ค่าเริ่มต้น 10000 ms) ระหว่างรอ process นั้นจะหยุดทำงานชั่วคราว ถ้ามีหลาย process ที่เขียนไฟล์เดียวกันบ่อยๆ ควรใช้ Postgres
db: sqlite({ url: 'file:./cms.db', busyTimeout: 5_000 })Postgres
npm install @easy-cms/db-postgrespnpm add @easy-cms/db-postgresyarn add @easy-cms/db-postgresbun add @easy-cms/db-postgresimport { postgres } from '@easy-cms/db-postgres'
db: postgres({ url: process.env.DATABASE_URL }) // a server, via postgres.js
db: postgres({ pglite: '.pglite' }) // PGlite: Postgres in WebAssembly, needs @electric-sql/pglitePGlite สะดวกสำหรับใช้งานในเครื่องและในเทสต์: เป็น Postgres จริงโดยไม่ต้องติดตั้งอะไร การตั้งค่าที่พบบ่อย:
db: process.env.DATABASE_URL ? postgres({ url: process.env.DATABASE_URL }) : postgres({ pglite: '.pglite' }),ตัวเลือกทั่วไป
| ตัวเลือก | ค่าเริ่มต้น | |
|---|---|---|
tablePrefix | ecms_ | prefix ของทุกตารางที่ Easy CMS สร้าง |
migrationDir | easy-cms/migrations | ตำแหน่งเก็บไฟล์ migration |
ใช้ฐานข้อมูลร่วมกับแอปของคุณ
Easy CMS สร้างและแก้ไขเฉพาะตารางที่มี prefix ของตัวเอง จึงใช้ฐานข้อมูลของแอปคุณได้ ตารางของคุณเองจะไม่ถูกแตะต้อง ทั้งในช่วงพัฒนา (development) และโดย migration
ข้อแตกต่างที่ควรรู้
- การเรียงข้อความเป็นไปตาม collation ของฐานข้อมูล: SQLite และ PGlite เรียงแบบแยกตัวพิมพ์เล็ก-ใหญ่ ส่วน Postgres server ส่วนใหญ่ไม่แยก
- ไฟล์ migration สร้างขึ้นสำหรับฐานข้อมูลชนิดเดียว ไฟล์ที่สร้างสำหรับ SQLite จะถูกปฏิเสธบน Postgres
ประสิทธิภาพ
วัดด้วย packages/integration/load.ts บน Postgres 17 (Docker บนโน้ตบุ๊ก 10 คอร์): บทความ 100,000 รายการ มีสองภาษา, drafts และ versions, relationship, tag แบบ hasMany และ blocks ยิง REST พร้อมกัน 20 request และ connection pool 10
| Request | Request/วินาที | p50 | p95 |
|---|---|---|---|
ตาม id พร้อม populate relationship (depth=2) | 2,750 | 8 ms | 10 ms |
ตาม slug (where[slug][equals]) | 2,770 | 8 ms | 10 ms |
| หน้าแรกของรายการ | 1,060 | 18 ms | 23 ms |
| กรองตาม relationship เรียงตามวันที่ | 560 | 34 ms | 55 ms |
| รายการใน admin รวมฉบับร่าง | 550 | 35 ms | 49 ms |
| บันทึกฉบับร่าง (พร้อม version) | 500 | 38 ms | 52 ms |
| สุ่มหน้าจาก 8,000 หน้า | 150 | 129 ms | 189 ms |
กรองตามค่า hasMany เรียงตามตัวเลข | 115 | 159 ms | 258 ms |
ค้นหาด้วย like | 100 | 198 ms | 262 ms |
ค้นในบล็อก (layout.blockType) | 83 | 237 ms | 304 ms |
ความหมายสำหรับเว็บของคุณ:
- หน้าเว็บและการดึงตาม id/slug เร็ว frontend ส่วนใหญ่ดึงตาม id หรือ slug และแสดงรายการหน้าแรกๆ
- หน้าลึกๆ ใช้เวลามากขึ้น ตามระยะ เพราะฐานข้อมูลต้องข้ามแถวก่อนหน้า ให้แบ่งหน้า archive ตามวันที่ (
where[publishedAt][lt]=…) แทนการไปหน้าที่ 5,000 likeอ่านทุกแถว ถ้าต้องการค้นหาทั้งเว็บ ให้ใช้บริการค้นหา (Meilisearch, Algolia, Typesense) ที่อัปเดตผ่าน webhooks หรือเพิ่ม indexpg_trgmบน Postgres เอง- การค้นในบล็อก อ่าน JSON ของทุกเอกสาร บน Postgres ตัวดำเนินการ
equalsและinใช้ JSON containment จึงเร็วกว่าตัวอื่นประมาณหกเท่า ควรใช้กับการกรอง ไม่ใช่ทุกครั้งที่มีคนเปิดหน้า - cache หน้าสาธารณะ (CDN หรือ cache ของ framework) แล้วสั่ง revalidate จาก webhook traffic ส่วนใหญ่จะไม่ต้องมาถึง CMS เลย
- ถ้ามี request พร้อมกันมากกว่าจำนวน connection จะต้องรอ connection ว่าง เพิ่ม
maxของpostgres()ได้ถ้าฐานข้อมูลรับไหว
ขั้นต่อไป
- Migration และการ deploy: migration บน production
- Backup และการอัปเกรด: สำรองฐานข้อมูล