Skip to content

ฐานข้อมูล ​

หน้านี้สอนอะไร

SQLite, Turso, Postgres และ PGlite: การเชื่อมต่อ การเลือก และการปรับแต่ง

ควรอ่านก่อน: เริ่มใช้งาน

SQLite ​

bash
npm install @easy-cms/db-sqlite
bash
pnpm add @easy-cms/db-sqlite
bash
yarn add @easy-cms/db-sqlite
bash
bun add @easy-cms/db-sqlite
ts
import { 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

ts
db: sqlite({ url: 'file:./cms.db', busyTimeout: 5_000 })

Postgres ​

bash
npm install @easy-cms/db-postgres
bash
pnpm add @easy-cms/db-postgres
bash
yarn add @easy-cms/db-postgres
bash
bun add @easy-cms/db-postgres
ts
import { 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/pglite

PGlite สะดวกสำหรับใช้งานในเครื่องและในเทสต์: เป็น Postgres จริงโดยไม่ต้องติดตั้งอะไร การตั้งค่าที่พบบ่อย:

ts
db: process.env.DATABASE_URL ? postgres({ url: process.env.DATABASE_URL }) : postgres({ pglite: '.pglite' }),

ตัวเลือกทั่วไป ​

ตัวเลือกค่าเริ่มต้น
tablePrefixecms_prefix ของทุกตารางที่ Easy CMS สร้าง
migrationDireasy-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

RequestRequest/วินาทีp50p95
ตาม id พร้อม populate relationship (depth=2)2,7508 ms10 ms
ตาม slug (where[slug][equals])2,7708 ms10 ms
หน้าแรกของรายการ1,06018 ms23 ms
กรองตาม relationship เรียงตามวันที่56034 ms55 ms
รายการใน admin รวมฉบับร่าง55035 ms49 ms
บันทึกฉบับร่าง (พร้อม version)50038 ms52 ms
สุ่มหน้าจาก 8,000 หน้า150129 ms189 ms
กรองตามค่า hasMany เรียงตามตัวเลข115159 ms258 ms
ค้นหาด้วย like100198 ms262 ms
ค้นในบล็อก (layout.blockType)83237 ms304 ms

ความหมายสำหรับเว็บของคุณ:

  • หน้าเว็บและการดึงตาม id/slug เร็ว frontend ส่วนใหญ่ดึงตาม id หรือ slug และแสดงรายการหน้าแรกๆ
  • หน้าลึกๆ ใช้เวลามากขึ้น ตามระยะ เพราะฐานข้อมูลต้องข้ามแถวก่อนหน้า ให้แบ่งหน้า archive ตามวันที่ (where[publishedAt][lt]=…) แทนการไปหน้าที่ 5,000
  • like อ่านทุกแถว ถ้าต้องการค้นหาทั้งเว็บ ให้ใช้บริการค้นหา (Meilisearch, Algolia, Typesense) ที่อัปเดตผ่าน webhooks หรือเพิ่ม index pg_trgm บน Postgres เอง
  • การค้นในบล็อก อ่าน JSON ของทุกเอกสาร บน Postgres ตัวดำเนินการ equals และ in ใช้ JSON containment จึงเร็วกว่าตัวอื่นประมาณหกเท่า ควรใช้กับการกรอง ไม่ใช่ทุกครั้งที่มีคนเปิดหน้า
  • cache หน้าสาธารณะ (CDN หรือ cache ของ framework) แล้วสั่ง revalidate จาก webhook traffic ส่วนใหญ่จะไม่ต้องมาถึง CMS เลย
  • ถ้ามี request พร้อมกันมากกว่าจำนวน connection จะต้องรอ connection ว่าง เพิ่ม max ของ postgres() ได้ถ้าฐานข้อมูลรับไหว

ขั้นต่อไป ​

เผยแพร่ภายใต้สัญญาอนุญาต MIT