- การทำ Durable Execution ไม่ได้จำเป็นต้องมีโครงสร้างพื้นฐานที่ซับซ้อนแยกต่างหากเสมอไป โดยหัวใจสำคัญคือการเก็บรักษาสถานะของเวิร์กโฟลว์อย่างปลอดภัย
- SQLite มอบสถานะแบบคงทนที่อิงธุรกรรมได้โดยไม่ต้องมีบริการฐานข้อมูลแยกต่างหาก และช่วยรักษาสถานะความคืบหน้าของเวิร์กโฟลว์ได้อย่างปลอดภัยโดยไม่มี network hop หรือ control plane เพิ่มเติม
- หากใช้ Litestream สตรีมการเปลี่ยนแปลงของ SQLite ไปยัง S3-compatible object storage แบบอะซิงโครนัส ก็จะสามารถรักษาสถานะไว้ใกล้กับรันไทม์ ขณะเดียวกันก็ทำสำเนาเพื่อวัตถุประสงค์ด้านแบ็กอัป การย้ายระบบ และการตรวจสอบได้
- สำหรับ เวิร์กโฟลว์แบบ bursty และเชิงทดลอง อย่าง AI agent การจัดวางแบบ micro VM หรือคอนเทนเนอร์ที่แต่ละเอเจนต์มีหน่วยสถานะ SQLite ขนาดเล็กเป็นอิสระของตัวเองนั้น เรียบง่ายกว่า ถูกกว่า และได้เปรียบด้านการแยกความเสียหายมากกว่าระบบแชร์ขนาดใหญ่เพียงชุดเดียว
- หากต้องการ high availability หรือการขยายตัวร่วมกันในวงกว้าง Postgres จะเหมาะกว่า แต่ระบบเวิร์กโฟลว์จำนวนมากไม่ได้ต้องการโครงสร้างพื้นฐานระดับนั้นตั้งแต่ช่วงเริ่มต้น
หัวใจของการทำงานแบบคงทน
- มักมีการพูดถึงการทำงานแบบคงทนราวกับว่าต้องพึ่งโครงสร้างพื้นฐานแบบคงทน แต่ในความเป็นจริงสิ่งสำคัญคือ workflow state และส่วนคอมพิวต์สามารถคงไว้ให้ราคาถูกและเปลี่ยนทดแทนได้
- ใน Obelisk สถานะความคืบหน้าของเวิร์กโฟลว์จะถูกเก็บไว้ใน execution log โดยสามารถ replay จากประวัติที่ถูกทำให้คงทนไว้ และ activity สามารถ retry ได้
ทำไม SQLite จึงเหมาะสม
- SQLite มอบ สถานะแบบคงทนที่อิงธุรกรรม ได้โดยไม่ต้องเพิ่มบริการฐานข้อมูลแยกต่างหาก
- สามารถรักษาสถานะความคืบหน้าของเวิร์กโฟลว์ได้อย่างปลอดภัย โดยไม่ต้องมี network hop, control plane เพิ่มเติม หรือภาระการปฏิบัติการใหม่
- ในหลายระบบ ไฟล์ฐานข้อมูลแบบโลคัลก็คือระดับของโครงสร้างพื้นฐานที่เหมาะสมพอดี
เพิ่มความพกพาได้ด้วย Litestream
- Litestream สตรีมการเปลี่ยนแปลงของ SQLite ไปยัง S3-compatible object storage แบบอะซิงโครนัส ทำให้สามารถรักษาสถานะไว้ใกล้กับรันไทม์ พร้อมรองรับการทำสำเนาเพื่อแบ็กอัป การย้ายระบบ และการตรวจสอบ
- ข้อควรระวัง: การทำ replication ของ Litestream เป็นแบบอะซิงโครนัส ดังนั้นหากโวลุ่ม SQLite หายไปก่อนที่ข้อมูลจะถูกคัดลอก การเขียนล่าสุดบนเครื่องที่ยังไม่ได้ทำสำเนาอาจหายไปตอนกู้คืน
- สำหรับเวิร์กโฟลว์ AI และเวิร์กโฟลว์เชิงทดลองจำนวนมาก เรื่องนี้อยู่ในระดับที่ยอมรับได้ แต่เป็นโมเดลที่ต่างจาก ฐานข้อมูลแชร์แบบ high availability
- โมเดลการปฏิบัติการเชิงใช้งานจริง: รันเซิร์ฟเวอร์ Obelisk พร้อมฐานข้อมูล SQLite, ใช้ Litestream สำหรับแบ็กอัป และให้ observer ดึงฐานข้อมูลเมื่อจำเป็น — ไฟล์เดียวกันนี้ยังนำกลับมาใช้สำหรับการ replay แบบโลคัล การดีบัก และการวิเคราะห์พฤติกรรมของเอเจนต์ได้
ทำไมจึงเหมาะกับ AI agent เป็นพิเศษ
- AI agent และเวิร์กโฟลว์ที่สร้างโดย AI มีลักษณะ bursty และเชิงทดลอง ดังนั้นการมี หน่วยสถานะแบบเล็กที่สมบูรณ์ในตัวเองสำหรับแต่ละเอเจนต์หรือแต่ละ tenant จึงเอื้อต่อการให้เหตุผลเกี่ยวกับระบบมากกว่า
- การจัดวางบน micro VM หรือคอนเทนเนอร์ เป็นฟลีตของเซิร์ฟเวอร์ขนาดเล็ก โดยแต่ละตัวดูแลฐานข้อมูล SQLite และแบ็กอัปไปยัง object storage อย่างอิสระ เรียบง่ายกว่า ถูกกว่า และได้เปรียบด้านการแยกความเสียหายมากกว่าระบบแชร์ขนาดใหญ่ที่ทำงานตลอดเวลาเพียงชุดเดียว
กรณีที่ควรใช้ Postgres
- Obelisk รองรับ Postgres เช่นกัน และเหมาะสำหรับกรณีที่ต้องการ high availability, การขยายตัวร่วมกันในวงกว้าง หรือคุณลักษณะการดีพลอยที่ฐานข้อมูลผ่านเครือข่ายเหมาะสมกว่า
- หากการ replication ไปยัง object storage แบบอะซิงโครนัสไม่ใช่ โมเดลความทนทาน ที่ต้องการ Postgres ก็จะเหมาะสมกว่า
- ระบบเวิร์กโฟลว์จำนวนมากไม่จำเป็นต้องเริ่มต้นด้วยโครงสร้างพื้นฐานที่สูงเกินกว่าระดับที่สถานะของระบบต้องการจริงในช่วงแรก
- เพียงใช้ SQLite แบบโลคัล + แบ็กอัป S3 ด้วย Litestream + เวิร์กเกอร์ราคาประหยัด ก็สามารถสร้าง ระบบแบบคงทนด้วยโครงสร้างพื้นฐานขั้นต่ำ ได้ และอาจเป็นค่าเริ่มต้นที่สมเหตุสมผลที่สุดในสภาพแวดล้อม AI agent
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เพิ่งเริ่มจัดเวิร์กโฟลว์ด้วย Temporal ซึ่งสำหรับแอปโลคัลถือว่าดีพลอยได้ค่อนข้างเบา และใช้ SQLite ในการติดตั้งแบบโลคัลที่แยกขาดจากกัน
มันทำให้การจัดการ retry ของ API รวมถึงการจัดระเบียบเวิร์กโฟลว์และงานต่าง ๆ ง่ายขึ้นมาก เลยอยากแนะนำให้ลองใช้ดู ในเชิงแนวคิดก็ไปในทิศทางเดียวกับที่บทความนี้เสนอแบบตรงเป๊ะ แต่เพิ่มอินเทอร์เฟซที่ทั้งยืดหยุ่นและมีความสามารถสูง ซึ่งเหมาะกับการใช้งานโดยเอเจนต์มาก และยังดูเวิร์กโฟลว์ผ่านเว็บ UI หรือตรวจสอบการรันของเอเจนต์ได้ง่ายด้วย
Temporal เพิ่มความน่าเชื่อถือให้ระบบได้มากแบบแทบไม่ต้องออกแรงอะไรเลย ระบบแบบกระจายและเชื่อถือได้เป็นเรื่องยาก ดังนั้นผมคิดว่าอย่าสร้างวงล้อขึ้นใหม่จะดีกว่า
ถ้าคุณอยากเปิดดูฐานข้อมูล SQLite ได้ง่าย ๆ เข้าใจว่าเกิดอะไรขึ้นในเวิร์กโฟลว์ ประกอบงานย่อยแต่ละชิ้นเข้าด้วยกัน และทำให้การเรียกใช้เวิร์กโฟลว์เป็นเรื่องง่าย Temporal ก็น่าสนใจ
และพอใช้แบบนี้แล้ว การใช้ไฟล์สำหรับเอเจนต์ก็แทบจะลดลงไปมาก Markdown กับ JSON ก็ดี แต่เวลาสร้างแอปโลคัลขนาดเล็กมันให้ความรู้สึกเหมือนเป็นกับดัก LLM จัดการกับ SQLite ได้ดี และจากตรงนั้นก็เรนเดอร์ออกมาเป็น Markdown, JSON หรือรูปแบบอื่นที่ต้องการได้ ถ้าเอเจนต์ query แค่บางแถวที่ต้องการได้ แทนที่จะต้องเปิด
jqหรือgrepกับ Markdown ก็ประหยัดโทเคนได้มาก คุณยังได้ระบบจัดการข้อมูลแบบพกพาและรวมทุกอย่างไว้ในตัวเอง ที่บังคับให้โครงสร้างข้อมูลมีระเบียบมากกว่าการใช้หลายไฟล์ เมื่อโปรเจกต์โลคัลเล็ก ๆ โตขึ้นหรือเริ่มเป็นทางการมากขึ้น ก็ไปต่อที่ MySQL/Postgres ได้ และตอนนั้นคุณก็มีทั้ง schema และวินัยด้านข้อมูลอยู่แล้วTemporal จะซับซ้อนขึ้นมากเมื่อขยายสเกล การดูแล Cassandra ไม่ได้สนุกเลย และ Ringpop กับ TChannel ก็แก้บั๊กยากมากเวลาเกิดปัญหา ฝั่ง SQL backend ก็รองรับได้แค่อินสแตนซ์เดียว ไม่รองรับ replica สำหรับการสเกลแนวนอนเพราะข้อกำหนดด้านความสอดคล้องของข้อมูล
การแก้โค้ดที่ฝังอยู่ในเวิร์กโฟลว์ก็ซับซ้อนขึ้นได้เช่นกัน ขึ้นอยู่กับวิธีที่คุณเขียนโค้ด การเปลี่ยนแปลงที่ทำให้ลำดับ history event เปลี่ยนไป จะทำลาย determinism ของ worker ที่ดีพลอยไปแล้ว
พวกเราใช้ Temporal กันเยอะ คนที่เริ่มจากสคริปต์ง่าย ๆ หรือระบบอัตโนมัติจะชอบกันหมด แต่คนที่สร้างระบบโปรดักชันจริงบนมันกลับไม่ชอบกันเลย อาจเป็นเพราะเราบริหารจัดการมันไม่เก่งก็ได้ แต่ภาพสวยหรูที่เห็นในคอมเมนต์พวกนี้ไม่ตรงกับประสบการณ์ของผม
ผมยังไม่เคยใช้เอง แต่อยากฟังประสบการณ์จริงเพิ่ม
ไม่ค่อยเข้าใจความยึดติดกับการใช้ SQLite ในแอปที่รันใช้งานจริงนัก SQLite เป็นฐานข้อมูลแบบฝังตัว จึงไม่เหมาะกับการจัดการคอนเคอร์เรนซีเลย
นี่คือเหตุผลที่มีเซิร์ฟเวอร์ฐานข้อมูลอย่าง Postgres และ MySQL อยู่แล้ว หน้าที่ทั้งหมดของมันคือเปิดให้หลายโปรเซสแก้ไขข้อมูลพร้อมกันได้จากคนละเครื่อง
นี่เป็นหลักการพื้นฐานของวิทยาการคอมพิวเตอร์ ดังนั้นฝั่งที่ตะโกนว่า “SQLite สำหรับทุกอย่าง” จึงดูเหมือนยังมีประสบการณ์ไม่มากนัก
SQLite เป็นฐานข้อมูลสำหรับงาน production ที่ยอดเยี่ยมสำหรับเวิร์กโหลดจริงจำนวนมาก และเรื่องนี้ก็มีเอกสารรองรับอย่างแพร่หลาย เพียงแต่มันต่างจาก Postgres มาก จึงต้องเรียนรู้เทคนิคอีกชุดหนึ่งโดยสิ้นเชิง
มุมมองหนึ่งคือ SQLite อาจเหมาะมากกับส่วนของระบบที่มีการแบ่งพาร์ทิชันอย่างชัดเจนโดยธรรมชาติ
net/httpก็เพียงพอให้บริการบางประเภทรับภาระงานได้ทั้งหมดเท่าที่จะจินตนาการได้ ยิ่งเป็นจริงมากขึ้นถ้าสามารถเพิ่มสเปกฮาร์ดแวร์ตามเวลาได้ และ SQLite ก็สเกลไปได้ถึงระดับหลายแสน TPS อย่างไม่ซับซ้อนสิ่งที่ยอมสละไปจริง ๆ คือเรื่อง ความพร้อมใช้งานสูง/การสลับระบบเมื่อขัดข้อง และการกู้คืนจากภัยพิบัติ ซึ่งเรื่องเหล่านี้ก็ยังมีทางแก้ ระบบแบบเซิร์ฟเวอร์เดี่ยวโดยมากแล้วแข็งแรงกว่าที่คิดมาก เพราะเมื่อไม่มี control plane ที่ซับซ้อน หลายครั้งระบบยิ่งขยาย จำนวน uptime กลับยิ่งลดลง
ผมชอบการนำ “best practice” เดิม ๆ กลับมาประเมินใหม่ตามการเปลี่ยนแปลงของเทคโนโลยี โดยเฉพาะถ้ามันพาไปสู่ความเรียบง่ายมากขึ้น การรันโซเชียลมีเดียสำหรับครอบครัวบน SQLite DB เดียวใน VPS เครื่องเดียวถือว่ายอดเยี่ยม มีผู้ใช้ราว 15 คนและแทบไม่ต้องดูแลรักษาเลย อินสแตนซ์ FreshRSS กับหน้า “now” ก็รันบน SQLite เช่นกัน
ที่ทำงานเองก็ใช้ SQLite มาตลอดหลายทศวรรษในสารพัดงาน ทั้งเป็นคิวงานชั่วคราว ใช้โหลดและคิวรีล็อกจำนวนมากในเครื่องอย่างรวดเร็ว และใช้แสดงผล/กรองแบบเรียลไทม์ด้วย https://github.com/simonw/datasette ที่ยอดเยี่ยมของ simonw
มันใกล้กับแนวคิด “SQLite ในที่ที่มากกว่าที่คุณคิด” มากกว่า “SQLite สำหรับทุกอย่าง”
งาน SQLite ที่ขอบเครือข่ายของ kentonv/Cloudflare อาจทำให้แนวคิดนี้เป็นที่แพร่หลายขึ้นบ้าง แต่จริง ๆ แล้วมันเป็นกระแสที่มีอยู่ก่อนแล้ว https://blog.cloudflare.com/sqlite-in-durable-objects/
การรู้จักและอยากนำกรณีใช้งานเล็ก ๆ แต่มีประโยชน์เหล่านี้ไปใช้ ไม่ใช่สัญญาณของการขาดประสบการณ์ ตรงกันข้าม มันอาจเป็นตัวชี้วัดของประสบการณ์ก็ได้
มีความเป็นไปได้สูงว่า SQLite ถูกใช้งานมากกว่าระบบฐานข้อมูลอื่นทั้งหมดรวมกัน ในโลกจริงมีสำเนาของ SQLite อยู่หลายพันล้านชุด ทั้งในอุปกรณ์ Android, iPhone และอุปกรณ์ iOS, Mac, เครื่องที่ติดตั้ง Windows 10/11, Firefox/Chrome/Safari, Skype, iTunes, ไคลเอนต์ Dropbox, TurboTax และ QuickBooks, PHP และ Python, ทีวีและเซ็ตท็อปบ็อกซ์ส่วนใหญ่, ระบบมัลติมีเดียในรถยนต์ส่วนใหญ่ และแอปพลิเคชันอีกนับไม่ถ้วน
https://sqlite.org/mostdeployed.html
วิธีนี้ทำให้เข้าใจเรื่องการสเกลได้ง่ายกว่ามาก แค่แยกออก แล้วแยกอีก โดยเพิ่มชาร์ดอีกหนึ่งชุดต่อผู้ใช้จำนวน N คน
แน่นอนว่าคุณจะได้ปัญหาอีกแบบแทน เช่นคิวรีข้ามชาร์ดอย่างงานวิเคราะห์ หรือจะกระจายโหลดอย่างไรเมื่อผู้ใช้เลิกใช้หรือเมื่อข้อมูลเก่าลง
แต่คุณสามารถหลีกเลี่ยงปัญหาการสเกลของ shared index ทั้งก้อนที่เกิดจากการ insert/update เมื่อมีผู้ใช้จำนวนมากได้
มันจะไม่ใช่ฐานข้อมูลเชิงสัมพันธ์เท่าไรนัก แต่จะกลายเป็นฐานข้อมูลแบบลำดับชั้นมากกว่า
แทนที่สิ่งต่อไปนี้ทั้งหมดด้วย Go + SQLite: Intercom, Zendesk, อีเมลมาร์เก็ตติ้ง, Kanban, Todo, payment stack, issue tracker, ฟอรัม, ระบบมอนิเตอร์ uptime, โคลน PagerDuty
เพราะสินค้าที่ขายมีหลายสิบตัว เลยคิดว่าทำเองทั้งหมดไปเลยจะเป็นอย่างไร
ทุกอย่างรันอยู่บนเซิร์ฟเวอร์เดียวกันและใช้หน่วยความจำน้อยมาก เลิกใช้เครื่องมือ SaaS ที่เคยใช้อยู่ทั้งหมดแล้วแทนด้วยสิ่งเหล่านี้
หลังย้ายไปใช้เซิร์ฟเวอร์เฉพาะ ค่าใช้จ่ายลดเหลือราว 1/10 ของที่เคยจ่ายให้ managed cloud solution อีกทั้งยังได้ latency ต่ำลงโดยยังคง high availability ระดับเดิมไว้ด้วย ส่วนหนึ่งก็เพราะ tail latency เคยแย่ลงจากปัญหา noisy neighbor บน VPS
เมื่อก่อนใช้เงินไปกับของพวกนี้เยอะมาก แต่ตอนนี้รันมา 4 เดือนแล้วและแทบต้องอัปเดตแค่เล็กน้อย
การ deploy เรียบง่ายมาก ไม่มีทั้ง Docker และ Kubernetes มีแค่ systemd service กับไบนารีที่ build จากเครื่องพัฒนาแล้วนำไป deploy
ก่อนหน้านี้ก็เคยจ่ายเงินให้บริการอย่าง MaxMind หรือ IPData แต่สุดท้ายทำบริการระบุตำแหน่งทางภูมิศาสตร์จาก IP ขึ้นมาเอง และในการทดสอบมันทำได้ดีกว่าโซลูชันเดิมส่วนใหญ่
เริ่มจากแทน Uptime Robot ก่อน แล้วพอมั่นใจก็แทน PagerDuty ต่อ จากนั้นก็แทน Intercom
สุดท้าย แม้จะได้ยินมาตลอดว่า “อย่าสร้าง payment stack เอง” แต่ก็คิดว่า YOLO เลยตัดสินใจลองทำพลาดนั้นด้วยตัวเอง ศึกษาโซลูชันการชำระเงินที่มีอยู่แล้วพัฒนาและ deploy เอง ซึ่งจนถึงตอนนี้ยังไม่มีปัญหาอะไรเลย
ด้านหน้าวาง Caddy ไว้
แล้วก็พบว่าโดยมากฟีเจอร์ของผลิตภัณฑ์ SaaS เราใช้งานจริงแค่ 1~5% เท่านั้น ขณะที่ฟีเจอร์ที่จำเป็นจริง ๆ กลับยิ่งถูกฝังลึกลงไปในแพลตฟอร์ม “ระดับองค์กร” พวกนี้จนทำให้ workflow ยุ่งยากขึ้น
จะไม่โชว์ตัวผลิตภัณฑ์เชิงพาณิชย์ เพราะพาร์ตเนอร์และลูกค้าคงไม่ชอบถ้ารู้ว่าฉันทำของได้ถูกแค่ไหน แต่ฉันเรียกสิ่งนี้ว่าความมีไหวพริบ
แต่แอปฟรีโชว์ได้ เพิ่งเปิดตัวไม่นานและมีผู้ใช้เกิน 20,000 คนแล้ว: https://macrocodex.app/
แอปนี้ใช้แค่โคลน Zendesk เท่านั้น ส่วนอีเมลจัดการผ่าน Cloudflare routing เลยแทบไม่มีต้นทุนในการรัน
ช่องว่างระหว่างไฟล์กับฐานข้อมูลแบบหลายพาร์ทิชันนั้นกว้างมาก การรันฐานข้อมูลในคอนเทนเนอร์ในงานที่ระบบโปรดักชันผูกอยู่ด้วยไม่ใช่สไตล์ของฉัน
ส่วนตัวคิดว่างาน ETL จำนวนมากทำบนเครื่องโลคัลได้โดยไม่ต้องดึงฐานข้อมูลระดับองค์กรเข้ามาใช้ ในกรณีแบบนั้น DuckDB ดีกว่า SQLite ราว 5~10 เท่า และยังง่ายกับเร็วกว่าเยอะเมื่อเทียบกับการตั้งฐานข้อมูล Postgres แยกขึ้นมา
สำหรับงานสคริปต์ทั่วไป สคริปต์ awk 20 บรรทัดเทียบกับสคริปต์ SQL ที่ให้ผลเท่ากันบน DuckDB ซึ่งสะอาด แข็งแรง และดูแลรักษาง่ายกว่ามากนั้น แทบเทียบกันไม่ได้เลย
หวังว่า MotherDuck จะไม่ต้องปั่นกระแสแล้วเทขายเพื่อทำ IPO ถ้าต้องเสียเครื่องมือนี้ไปเพราะความโลภแบบบริษัททั่วไปก็คงน่าเสียดายมาก
เรื่องสคริปต์ awk 20 บรรทัดนี่น่าสนใจ เพราะเมื่อวานฉันก็พูดประเด็นแทบเดียวกันที่ Ubuntu Summit คือพอถึงจุดหนึ่ง การเขียนเชลล์สคริปต์ด้วย GNU coreutils จะเริ่มไม่สมเหตุสมผล และสคริปต์ DuckDB SQL จะขยายต่อได้ดีกว่าทั้งในแง่ความซับซ้อน การดูแลรักษา และบ่อยครั้งรวมถึงประสิทธิภาพด้วย สไลด์อยู่ที่นี่: https://blobs.duckdb.org/slides/duckdb-ubuntu-summit-2026.pd... หน้า 32~36
อีกอย่าง MotherDuck พัฒนา DBaaS แบบปิดซอร์สบน DuckDB สร้างอยู่บน DuckDB และเชื่อมต่อจาก DuckDB ไปยัง MotherDuck แต่เป็นบริษัทแยกต่างหากที่ได้รับเงินลงทุนจาก VC และมีสำนักงานใหญ่ในซีแอตเทิล
ส่วน DuckDB นั้นพัฒนาโดย DuckLabs ซึ่งเป็นบริษัทแบบ bootstrap หรือบริษัทที่ขับเคลื่อนด้วยรายได้ ตั้งอยู่ที่อัมสเตอร์ดัม ทรัพย์สินทางปัญญาของโครงการอยู่กับองค์กรที่สามคือ DuckDB Foundation ซึ่งเป็นองค์กรไม่แสวงหากำไรในเนเธอร์แลนด์ รายละเอียดดูได้ที่ https://duckdb.org/faq#how-are-duckdb-the-duckdb-foundation-...
ฉันสร้างไลบรารีที่ช่วยให้ อัปเดตพร้อมกัน กับ SQLite DB บน S3 ได้อย่างปลอดภัย[0]
มันทำงานได้ค่อนข้างมีประสิทธิภาพและปลอดภัย โดยใช้ SQLite sessions extension ที่ไม่ค่อยมีคนรู้จัก ร่วมกับ S3 compare-and-swap สำหรับไฟล์เมตาดาต้าขนาดเล็ก ตอนนี้ใช้มันอย่างมีความสุขในโปรเจ็กต์เล็ก ๆ หลายตัวที่ต้องการฐานข้อมูลเก็บสถานะสำหรับฟังก์ชัน Lambda แต่ไม่อยากจ่ายค่าฐานข้อมูลอินสแตนซ์เต็มรูปแบบ
[0]: https://github.com/psanford/s3db
SQLite มีประสิทธิภาพน่าทึ่งมากสำหรับ แอปพลิเคชันโหนดเดียว แม้เทียบกับ Postgres ก็ตาม
Postgres ใช้หน่วยความจำมากกว่ามาก และ I/O ต้องผ่านการสื่อสารระหว่างโปรเซส ขณะที่ SQLite สามารถเก็บทุกอย่างไว้ในโปรเซสได้ผ่าน shared connection pool
ตอนนี้กำลังทดสอบ storage engine หลายตัวสำหรับ agent harness โดย SQLite รองรับได้ถึง 7.5 พันเซสชันพร้อมกันบน vCPU เดียว แต่ Postgres กลับล่มหรือไม่ก็ connection หมด
[0] https://github.com/impalasys/talon/pull/23#issuecomment-4577...
ทันทีที่ต้องออกจากเธรดปัจจุบัน เกมด้าน latency ก็แทบแพ้แล้ว ถ้าไม่บังคับให้มีการสื่อสารระหว่างเธรด SQLite สามารถทำงานในระดับไมโครวินาทีได้
ในบริบทของโหนดเดียว Postgres ถือว่ามากเกินความจำเป็น ไม่ควรคาดหวังให้มันมาแข่งกับ SQLite
มันแทบเหมือนกับการเอา HashMap ในหน่วยความจำมาเบนช์มาร์กเทียบกับ Redis แล้วแปลกใจว่า HashMap ออกมาดีในสภาวะอุดมคติ
อ่านเรื่อง SQLite มาหลายปีแล้วเลยลองเอามาใช้กับโปรเจกต์ส่วนตัว แต่พอมาจากฝั่ง Postgres แล้วรู้สึกช็อกมากที่ระบบชนิดข้อมูลมันอ่อนมาก
ด้อยจริง ๆ ไม่เข้าใจว่าทำไมถึงถูกยกย่องกันขนาดนั้น
https://sqlite.org/datatype3.html
https://www.postgresql.org/docs/current/datatype.html
ความรู้สึกเวลาใช้งานวันที่/เวลานี่เหมือนกำลังใช้ฐานข้อมูลอายุ 30 ปี และตอน insert ก็ไม่ได้บังคับอะไรเลย ใครก็ได้ช่วยอธิบายทีว่าทำไมคนถึงชอบกันเยอะขนาดนี้
PRAGMA journal_mode = WAL
PRAGMA foreign_keys = ON
Something non-null
PRAGMA busy_timeout = 1000This is fine for most applications, but see the manual
PRAGMA synchronous = NORMALIf you use it as a file format
PRAGMA trusted_schema = OFFอาจต้องมีตัวเลือกเพิ่มตาม binding ที่ใช้ ตัวอย่างเช่นแอป Python ไม่ควรใช้ค่าเริ่มต้นของโมดูล sqlite3 เพราะค่าเริ่มต้นนั้นผิดไปเลย ก่อน 3.12 ก็แทบไม่มีทางเลือกนอกจากใช้ binding นอก standard library: https://docs.python.org/3/library/sqlite3.html#transaction-c...
ควรใช้ strict table ด้วย https://www.sqlite.org/stricttables.html
แม้จะใช้งานไม่ค่อยสะดวก แต่ก็ใช้ข้อจำกัด CHECK ได้ด้วย เช่น ถ้าจะใช้กับการรองรับวันที่แบบ built-in ของ SQLite แม้ทำได้แต่ก็ดูฝืน ๆ:
CHECK (
date(my_date_col) IS NOT NULL
AND my_date_col = date(my_date_col)
)
ที่ต้องมี IS NOT NULL เพราะ date จะคืนค่า NULL เมื่อวันที่ไม่ถูกต้อง ส่วนเงื่อนไขอีกอันจำเป็นเพราะมันยอมรับ Julian day ด้วย โดย date('2026') จะกลายเป็นช่วงเวลาหนึ่งในปี 4707 ก่อนคริสตกาล
โดยเฉพาะก่อนมี strict table ก็เห็นด้วยว่าน่าผิดหวัง
ควรดู DuckDB มันใกล้เคียงกับ SQLite ที่มีชนิดข้อมูลดี ๆ เพียงแต่มันเป็น OLAP คือ array of structs ไม่ใช่ OLTP คือ struct of arrays ดังนั้นกับโหลดแบบ SQLite ทั่วไปอาจช้ากว่า ในทางปฏิบัติถ้าเป็นแอปที่กำลังพิจารณาสองตัวนี้อยู่ ความต่างคงไม่ใหญ่มาก
เคยใช้Postgres clusterขนาดใหญ่หลายชุดแล้วค่อยย้ายมา SQLite และตอนนี้บริการที่มีผู้ใช้ต่อเดือนระดับ 7 หลักทั้งหมดก็รันอยู่บน SQLite durable objects
ต้องคิดรูปแบบการเข้าถึงใหม่ แต่ข้อดีก็คุ้มค่ามาก
เป็นการวางกรอบที่ดี ถ้าปัญหาหลักคือการเก็บสถานะของเวิร์กโฟลว์ให้คงทนถาวร ตรวจสอบย้อนหลังได้ และกู้คืนได้ง่าย หลายกรณี SQLite ก็เพียงพอ
อยากเห็นเวอร์ชันถัดไปของแนวคิดนี้เร็ว ๆ ว่า “เวิร์กโฟลว์แบบคงทนถาวรต้องมีแค่ log ก็พอ”
เหตุผลหนึ่งที่โซลูชันแนว “มีแค่ log ก็พอ” อาจล้มเหลวได้ คือเมื่อ log ที่ไม่น่าเชื่อถือกลายเป็นช่องทางโจมตีแบบ injection[1]
อย่าลืมตรวจสอบ SBOM และรวม CI/CD pipeline เข้าไปด้วย[2]
[1] https://news.ycombinator.com/item?id=48315440
[2] https://github.com/jqwik-team/jqwik/issues/708#issuecomment-...
เอาจริง ๆ แล้ว ความเป็นผู้เชี่ยวชาญคือการเลือกใช้เครื่องมือให้เหมาะกับงาน