42 คะแนน โดย GN⁺ 14 일 전 | 26 ความคิดเห็น | แชร์ทาง WhatsApp
  • ฐานข้อมูลทุกชนิดท้ายที่สุดแล้วคือ ชุดไฟล์ที่มีโครงสร้างบนระบบไฟล์ ดังนั้นแอปพลิเคชันในระยะเริ่มต้นก็อาจได้ประสิทธิภาพเพียงพอแม้จะจัดการไฟล์เองโดยตรง
  • นำเซิร์ฟเวอร์แบบเดียวกันไปเขียนด้วย Go, Bun และ Rust แล้วเปรียบเทียบ 3 แนวทางคือ สแกนไฟล์, แผนที่ในหน่วยความจำ, ค้นหาแบบไบนารีบนดิสก์ ผลคือการเข้าถึงไฟล์แบบง่าย ๆ ก็ให้ throughput สูงได้
  • แนวทางแผนที่ในหน่วยความจำให้ประสิทธิภาพสูงสุด (สูงสุด 169k req/s) ส่วน SQLite ทำได้ 25k req/s อย่างสม่ำเสมอ แต่มี overhead
  • บริการส่วนใหญ่สามารถรองรับได้ถึงระดับ 90 ล้าน DAU ด้วยไฟล์ SQLite เพียงไฟล์เดียว และในช่วงเริ่มต้นของผลิตภัณฑ์ก็ไม่จำเป็นต้องมีฐานข้อมูลแยกต่างหาก
  • เมื่อชุดข้อมูลใหญ่เกิน RAM หรือเริ่มต้องการ join, การค้นหาหลายเงื่อนไข, การเขียนพร้อมกัน, transaction จึงค่อยถึงเวลาต้องใช้ฐานข้อมูล

จำเป็นต้องมีฐานข้อมูลจริงหรือ

  • ฐานข้อมูลก็คือชุดของไฟล์ในท้ายที่สุด โดย SQLite เป็นไฟล์เดียว ส่วน PostgreSQL ประกอบด้วยไดเรกทอรีและโปรเซส
    • ฐานข้อมูลทุกชนิดอ่านและเขียนลงไฟล์ซิสเต็ม และทำงานในลักษณะเดียวกับการเรียก open() จากโค้ด
    • ดังนั้นประเด็นสำคัญไม่ใช่ “จะเขียนไฟล์ไหม” แต่คือ “จะใช้ไฟล์ของฐานข้อมูล หรือจะจัดการเองโดยตรง
    • แอปพลิเคชันจำนวนมากในระยะเริ่มต้นก็ยังได้ประสิทธิภาพเพียงพอแม้จัดการเอง

โครงสร้างการทดลอง

  • สร้าง HTTP server แบบเดียวกันด้วย Go, Bun(TypeScript), Rust และเปรียบเทียบ 2 กลยุทธ์การจัดเก็บ
    • ใช้ไฟล์ JSONL 3 ไฟล์คือ users.jsonl, products.jsonl, orders.jsonl
    • สร้างด้วย POST /users และอ่านด้วย GET /users/:id
    • ใช้เฉพาะเส้นทางอ่าน (GET) เป็นเป้าหมายของการ benchmark
  • วิธีที่ 1: อ่านไฟล์ทุกครั้งที่มีคำขอ

    • เมื่อมีคำขอจะเปิดไฟล์ สแกนทุกบรรทัด parse JSON แล้วตรวจว่า ID ตรงกันหรือไม่
    • โดยเฉลี่ยต้องอ่านไฟล์ประมาณครึ่งหนึ่ง จึงมีความซับซ้อน O(n)
    • ยิ่งข้อมูลมาก ความเร็วในการประมวลผลคำขอก็ยิ่งลดลงอย่างรวดเร็ว
  • วิธีที่ 2: โหลดทั้งหมดขึ้นหน่วยความจำ

    • ตอนเริ่มต้นจะอ่านทั้งไฟล์แล้วเก็บไว้ใน hash map ตาม ID
    • การเขียนจะอัปเดตทั้ง map และไฟล์พร้อมกัน ส่วนการอ่านเป็นการ lookup จาก map ครั้งเดียวแบบ O(1)
    • ไฟล์ทำหน้าที่เป็นที่เก็บแบบถาวร ส่วน map ทำหน้าที่เป็นดัชนี
    • ใน Go ใช้ sync.RWMutex และใน Rust ใช้ RwLock เพื่อรองรับการอ่านแบบขนาน
  • วิธีที่ 3: ค้นหาแบบไบนารีจากดิสก์

    • เป็นทางสายกลางสำหรับการอ่านเร็วโดยไม่ต้องโหลดข้อมูลทั้งหมดเข้า RAM
    • สร้างไฟล์ข้อมูลที่เรียงตาม ID และ ไฟล์ดัชนี fixed-width (58 ไบต์/เรคอร์ด)
    • ใช้ ReadAt ค้นหาในดัชนีแบบ O(log n) แล้วอ่านเรคอร์ดเดียวจาก offset ที่พบ
    • เมื่อเพิ่มเรคอร์ดใหม่ ลำดับจะเสีย จึงต้องสร้างดัชนีใหม่หรือ merge เป็นระยะ
    • รูปแบบการ merge นี้คล้ายกับการทำงานของ LSM-tree

สภาพแวดล้อมการ benchmark

  • ขนาดชุดข้อมูล: 10k, 100k, 1M เรคอร์ด
  • เครื่องมือโหลด: wrk รันคำขอ GET แบบสุ่มเป็นเวลา 10 วินาที ด้วย 4 threads และ 50 concurrent connections
  • ทดสอบบนเครื่องเดียวกัน (Apple M1 Mac mini, macOS 15) ด้วย Go 1.26, Bun 1.3, Rust 1.94
  • ในฝั่ง Go มีการเปรียบเทียบเพิ่มกับ การค้นหาแบบไบนารี (ดิสก์) และ SQLite (modernc.org/sqlite)

ผลลัพธ์สำคัญ

  • linear scan ช้าลงชัดเจน: ที่ 1M เรคอร์ด Go เหลือ 23 req/s และ Bun เหลือ 19 req/s
  • การค้นหาแบบไบนารี (ดิสก์): ในช่วง 10k~1M เรคอร์ด ลดลงเพียง 15% จาก 45k → 38k req/s
    • อาศัยผลของ OS page cache ที่ทำให้พื้นที่ดัชนีส่วนบนอยู่ในหน่วยความจำตลอด
  • SQLite: 25k req/s, latency เฉลี่ย 2ms และยังคง ประสิทธิภาพสม่ำเสมอ
  • การค้นหาแบบไบนารีเร็วกว่า SQLite ราว 1.7 เท่า โดยสำหรับการ lookup ด้วย PK แบบง่าย SQLite มี overhead อยู่
  • แนวทาง map ในหน่วยความจำเร็วที่สุด: 97k~169k req/s, latency ต่ำกว่า 0.5ms
  • Bun เร็วกว่า Go: Bun 106k req/s, Go 97k req/s
    • Bun ใช้พื้นฐาน JavaScriptCore + Zig(uWebSockets) และข้าม libuv
  • Rust โดดเด่นมากใน linear scan: เร็วกว่า Go 3~6 เท่า คาดว่าเพราะประสิทธิภาพของ JSON parsing และ I/O
  • ตัวเลือกที่เหมาะที่สุดตามกรณีใช้งาน

    • throughput สูงสุดแบบเด็ดขาด: Rust map ในหน่วยความจำ (169k req/s)
    • ดีที่สุดเมื่อโหลดเข้า RAM ไม่ได้: Go การค้นหาแบบไบนารี (~40k req/s)
    • หากต้องใช้ SQL: SQLite (25k req/s)
    • ติดตั้งง่ายที่สุด: Go linear scan (~20 บรรทัดโค้ด)

ความหมายของ 25,000 req/s

  • ทราฟฟิกเว็บทั่วไปสมมติว่า อัตรา peak:average = 2:1
    • ค่าเฉลี่ย 12,500 req/s → ช่วงพีกประมาณ 25,000 req/s
  • สมมติว่าผู้ใช้ที่ active มีการอ่าน 10 ครั้งต่อชั่วโมง และมีอัตราใช้งานพร้อมกัน 10% ในช่วงพีก
    • สูตรคำขอช่วงพีก: DAU × 0.000278
  • ผลการคำนวณ DAU จนอิ่มตัวของแต่ละวิธี
    • Go linear scan: 2.8M
    • Go การค้นหาแบบไบนารี: 144M
    • SQLite: 90M
    • Go map ในหน่วยความจำ: 349M
    • Bun map ในหน่วยความจำ: 381M
    • Rust map ในหน่วยความจำ: 608M
  • ผลิตภัณฑ์ส่วนใหญ่ไปไม่ถึงตัวเลขนี้
    • ตัวอย่าง: ลูกค้า SaaS 10,000 ราย → 3 req/s, แอป 100,000 DAU → 30 req/s
  • สรุปคือ ผลิตภัณฑ์ระยะแรกส่วนใหญ่ไม่จำเป็นต้องมีฐานข้อมูล
    • ต่อให้จำเป็น ไฟล์ SQLite เพียงไฟล์เดียวก็ยังรองรับได้ถึง 90 ล้าน DAU

เมื่อไรจึงจำเป็นต้องมีฐานข้อมูล

  • เมื่อชุดข้อมูลใส่ใน RAM ไม่ได้

    • หากมีหลายสิบล้านเรคอร์ดขึ้นไป แค่ดัชนีก็กินพื้นที่หลาย GB
    • จำเป็นต้องมีการ paging ข้อมูล ซึ่งฐานข้อมูลจัดการเรื่องนี้ให้อัตโนมัติ
  • เมื่อต้องค้นหาด้วยฟิลด์อื่นที่ไม่ใช่ ID

    • หากต้องค้นหาหลายเงื่อนไข ก็ต้องสแกนไฟล์หรือเพิ่ม map อีก
    • ถ้าต้องดูแลหลาย map ก็แทบจะเท่ากับกำลังเขียน query engine เอง
  • เมื่อต้องใช้ join

    • ต้องอ่านหลายไฟล์มาประกอบกัน ซึ่ง SQL มีประสิทธิภาพมากกว่า
  • เมื่อมีการเขียนพร้อมกันจากหลายโปรเซส

    • map ในหน่วยความจำของแต่ละอินสแตนซ์แยกจากกัน ทำให้สูญเสียความสอดคล้อง
    • จึงต้องมีแหล่งข้อมูลจริงเพียงหนึ่งเดียวภายนอก → ซึ่งก็คือบทบาทของฐานข้อมูล
  • เมื่อต้องการการเขียนแบบ atomic ระหว่างหลายเอนทิตี

    • ต้องรับประกันว่าการสร้างคำสั่งซื้อและการตัดสต็อกจะสำเร็จหรือล้มเหลวพร้อมกัน
    • หากไม่ใช้ฐานข้อมูลก็ต้องทำ transaction log แยกเอง ขณะที่ DB แก้ด้วย ACID
    • หากไม่มีข้อจำกัดเหล่านี้ เช่น เครื่องมือภายใน, side project, ผลิตภัณฑ์ระยะแรก
    • ก็สามารถทำงานได้ดีบน RAM ของเซิร์ฟเวอร์เครื่องเดียว
    • และไฟล์ JSONL ก็ ย้ายไปฐานข้อมูลได้ง่าย ในภายหลัง

ภาคผนวกและโค้ดที่ให้มา

  • มีโค้ดเซิร์ฟเวอร์สำหรับ Go, Bun, Rust รวมอยู่ด้วย
  • มีข้อมูล seed และสคริปต์รัน benchmark (run_bench.sh) แยกให้
  • ในไฟล์ ZIP มี go-server/, bun-server/, rust-server/, seed.ts
  • สคริปต์จะ seed ข้อมูลทั้ง 3 ขนาด รันทดสอบโหลดด้วย wrk แล้วปิดการทำงาน

ข้อมูลเกี่ยวกับ DB Pro

  • DB Proเป็นไคลเอนต์ฐานข้อมูลสำหรับ Mac, Windows และ Linux

    • รวมความสามารถด้าน query, การสำรวจ และการจัดการไว้ในที่เดียว
    • รองรับแพลตฟอร์มเว็บสำหรับการทำงานร่วมกันและ AI ในตัว
    • เวอร์ชันล่าสุดรองรับ การเชื่อมต่อฐานข้อมูล SQLite ของ Val Town
    • ใน v1.3.0 เพิ่มความสามารถสร้างฐานข้อมูล, multi-query editor และการเชื่อมต่อ PlanetScale Vitess

26 ความคิดเห็น

 
happing94 14 일 전

นี่มันพูดบ้าอะไรเนี่ย
คิดว่าใช้ db เพราะเรื่องประสิทธิภาพเหรอ

 
unknowncyder 14 일 전

นั่นสิ ผมก็สงสัยว่าจะมีอินไซต์อะไรใหม่ไหม เลยไปดูต้นฉบับมาแล้วเหมือนกัน แต่นี่มันอะไรกัน...

แทนที่จะเปิดเรื่องด้วยประเด็นพื้นฐานอย่างเมโมรีแพงเลยต้องใช้ดิสก์บ้าง หรือเพื่อความเสถียรในการดูแลโปรดักชันบ้าง หรือเรื่อง atomicity บ้าง
แต่กลับเปิดมานั่งเทียบความเร็วกันดื้อ ๆ เลย ก็ได้แต่หลุดขำแห้งออกมาครับ

ทั้งที่ขาย DB อยู่แท้ ๆ แต่ก็ยังเขียนบทความประมาณว่า 'เราเป็นคนขาย DB แต่ DB ไม่ได้จำเป็นเสมอไปนะ!' แบบไม่เคอะเขิน เลยชวนให้สงสัยว่าอยากทำการตลาดหรือเปล่า -_-... ต่อให้พยายามมองในแง่บวก บางทีก็อดจะประชดนิด ๆ ไม่ได้เหมือนกัน

อย่างน้อยก็ถือว่าได้ benchmark มาก็แล้วกัน

 
myc0058 6 일 전

เป็นการเขียนโค้ดลอยๆ แบบฉบับมาตรฐานเลย

 
botplaysdice 13 일 전

ผมคิดว่านี่เป็นบทความที่ดีมาก โดยเฉพาะข้อมูลที่มี ‘ตัวเลข’ แบบนั้นยิ่งหายาก ในยุคที่หาได้ยากว่าจะได้เห็นนักพัฒนาที่อย่างน้อยก็ ‘พอมีภาพคร่าวๆ’ ว่าโค้ดที่เราสร้างและเทคสแตกที่เราหยิบมาใช้นั้นมีโอเวอร์เฮดอะไรอยู่บ้าง ผมอ่านอย่างเพลิดเพลินมาก

 
foriequal0 13 일 전

ผมก็เห็นด้วยเช่นกัน ผมคิดว่านี่เป็นข้อมูลที่ช่วยมอบสัญชาตญาณสำคัญเกี่ยวกับ Mechanical sympathy หรือการปรับจังหวะความเร็วของการพัฒนา เหมือนกับ "Latency Numbers Every Programmer Should Know"

และสำหรับผม บทความนี้ไม่ได้ชวนให้อ่านว่าทิศทางใดทิศทางหนึ่งดีกว่าอย่างไม่มีเงื่อนไข ตรงกันข้าม ผมกลับอ่านว่าตัวเลขที่แต่ละแนวทางซึ่งถูกกล่าวถึงในบทความแสดงออกมานั้นเป็น "ประสิทธิภาพที่เหลือเฟือเกินพอสำหรับธุรกิจส่วนใหญ่" ดังนั้นจึงเป็นการเสนอให้เลือกแนวทางที่เหมาะกับสถานการณ์ของปัญหามากกว่า

 
botplaysdice 13 일 전

อัญมณีในคำตอบก็เป็นของแถมด้วยครับ

 
white9s 13 일 전

ถ้ามีเหตุผลที่ต้องทำแบบนี้ ก็คงค่อยพิจารณากันได้ใช่ไหม? อย่างเช่นมีข้อจำกัดด้านประสิทธิภาพที่รุนแรงมาก
แต่ในกรณีส่วนใหญ่ มีเหตุผลจำเป็นอะไรที่ต้องเลือกวิธีนี้กันหรือเปล่า? ไม่ใช่ว่า DB จะไม่มีข้อดีเสียหน่อย..

 
m00nlygreat 13 일 전

ก็แค่อ่านได้ประมาณว่าเป็นการเปลี่ยนมุมคิดเท่านั้นเอง ทุกคนไวต่อประเด็นกันจังนะ

 
tazuya 13 일 전

ก็จริงนะครับ ถ้าในช่วงเริ่มต้นธุรกิจยังมีผู้ใช้ไม่มาก ก็อาจมองได้ว่าเป็นแค่ข้อเสนอว่าไม่ต้องซื้อ DB หรือทำระบบให้ซับซ้อน ใช้เพียงไฟล์ I/O พื้นฐานก็อาจพาธุรกิจไปจนตั้งหลักได้แล้ว

 
smash8106 13 일 전

ผมก็เห็นด้วยครับ บางครั้งในบริการต่าง ๆ DB ถูกให้ความสำคัญมากเกินความจำเป็น และบางทีก็ลงทุนกับการออกแบบมากเกินไป ราวกับว่าถ้าทำให้ normalization พังแล้วจะเกิดเรื่องใหญ่ขึ้นมาจริง ๆ ใช่ไหมครับ
ไม่ได้หมายความว่าไม่ควรใช้ DB แต่แค่อยากให้ลองรีเฟรชความคิดประมาณว่า เราใช้มันไปเพื่ออะไร และแก่นแท้ของบริการจริง ๆ คืออะไร แค่นี้ก็น่าจะเพียงพอและเป็นประโยชน์แล้วครับ
สุดท้ายแล้วเรื่องสมดุลสำคัญเสมอครับ

 
cafedead 14 일 전

ตั้งแต่วินาทีที่เลือกใช้ SQLite สำหรับเซิร์ฟเวอร์โปรดักชัน ก็ต้องคอยกังวลอยู่ตลอดว่าเมื่อไรควรย้ายไปใช้ตัวอื่น
สมัยก่อน ต้นทุนของตัว DB เอง (ค่าเครื่องเซิร์ฟเวอร์, IDC, ค่าไลเซนส์ ฯลฯ) สูง จึงพอมีเหตุผลให้ต้องคิดหนัก
แต่ทุกวันนี้มันตั้งค่าใช้งานได้ง่ายแบบที่เขาเรียกกันว่าคลิกเดียว แล้วจำเป็นต้องมานั่งกังวลเรื่องนี้จริง ๆ ไหม?

 
roxie 8 일 전

ตอนนี้ฐานข้อมูลก็ยังแพงอยู่นะ

 
csjune 12 일 전

แน่นอนว่า ถ้าเป็น "โปรเจ็กต์ระยะเริ่มต้นหรือแอปพลิเคชันขนาดเล็ก" ก็อาจไม่จำเป็นต้องมี DB ก็ได้ ไม่ใช่แค่ DB แต่ส่วนประกอบอื่น ๆ ก็ทำแบบคร่าว ๆ เลือกอะไรก็ได้เหมือนกัน ปัญหาคือเวลาที่สเกลใหญ่ขึ้น ก็เลยเป็นแค่บทความดูตัวเลขขำ ๆ เท่านั้นเอง

 
carnoxen 13 일 전

https://hackers.pub/@gnh1201/2025/…

บางครั้งก็ไม่จำเป็นต้องติดตั้งฐานข้อมูลแยกต่างหากเสมอไป แม้จะจำกัดเฉพาะบน Windows ก็ตาม...

 
roxie 8 일 전

เห็นชื่อเรื่องแล้วหลุดขำเลย

 
kuthia 13 일 전

บางครั้งผมก็คิดเหมือนกันว่า เอนทิตีหลัก ๆ จำเป็นต้องรับประกันความคงอยู่ถาวรผ่าน RDBMS จริงหรือไม่ เพราะเดี๋ยวนี้ก็มีเทคโนโลยีทางเลือกสำหรับทำหน้าที่เป็น SSOT อยู่พอสมควรเหมือนกัน

 
neptune 13 일 전

ถ้า SQLite พัง ก็หมดทางแก้เลย..

 
okxrr 13 일 전

มีเคสที่ sqlite เสียหายบ้างไหมครับ? อยากรู้ครับ โดยไม่นับกรณีการย้ายหรือลบไฟล์แบบผิดปกติ

 
GN⁺ 14 일 전
ความคิดเห็นจาก Hacker News
  • ชอบบทความนี้มาก มันแสดงให้เห็นได้ดีว่าคอมพิวเตอร์นั้นเร็วแค่ไหน
    แต่ไม่เห็นด้วยกับข้อสรุปช่วงท้าย ผู้เขียนบอกว่าแนวคิดนี้ใช้ไม่ได้กับแอปที่มีข้อจำกัดแบบ “หลายโปรเซสต้องเขียนพร้อมกัน” แต่ในความเป็นจริง แม้แต่โปรดักต์ช่วงเริ่มต้นก็มักมีกรณีที่ worker แยกอย่าง cron หรือ message queue ต้องเขียนพร้อมกัน
    จะบังคับให้มีแค่เมนเซิร์ฟเวอร์ที่เขียนก็ได้ แต่แบบนั้นจะเพิ่มความซับซ้อนของสถาปัตยกรรม
    ดังนั้นในมุมของสเกลล้วน ๆ ผมเห็นด้วยกับผู้เขียน แต่ถ้ามองกว้างกว่านั้น ผมคิดว่าใช้ฐานข้อมูลดีกว่า โดยเฉพาะ SQLite เป็นตัวเลือกที่สมเหตุสมผล
    ถ้าต้องการสเกล ก็แค่แคชข้อมูลที่เข้าถึงบ่อยไว้ในหน่วยความจำ ชุดที่ผมใช้คือ SQLite + in-memory cache

    • ผมก็เจอสถานการณ์คล้ายกันบ่อย ต่อให้เซิร์ฟเวอร์เครื่องเดียวพอ แต่พอถึงจุดที่ต้องมีการทำเซิร์ฟเวอร์สำรองซ้ำซ้อน ก็จำเป็นต้องใช้ network storage และสุดท้ายก็โน้มไปหาฐานข้อมูลที่เข้าถึงผ่านเครือข่ายได้
      บางครั้ง S3 ก็พอใช้ได้ แต่ก็ยังมีข้อจำกัดมากถ้าจะใช้แทนทั้งหมด
    • ทุกวันนี้เวลาเริ่มโปรเจกต์ใหม่ ผมใช้ SQLite เป็นค่าเริ่มต้น ประสิทธิภาพเร็วมาก และถ้าภายหลังขยายใหญ่ขึ้นก็ย้ายไป Postgres ได้ไม่ยาก
      ไม่ต้องดูแล DB server แยกหรือต้องจัดการแบ็กอัปเอง ทำให้เรียบง่ายและถูกกว่ามาก
    • หลังจากดู Rust 1M benchmark ก็ทำให้ตระหนักอีกครั้งว่าคอมพิวเตอร์สมัยนี้เร็วขนาดไหน
  • ผมชอบ SQLite มาก แต่ก็ได้เรียนรู้ว่ามันไม่ใช่คำตอบของทุกปัญหา
    ตอนทำแอปพจนานุกรมฝั่งไคลเอนต์ ผมลองใช้ SQLite wasm port แต่ไฟล์ DB ใหญ่กว่าที่คิด บีบอัดก็ไม่ค่อยดี และโหลดช้า
    สุดท้ายเลยเปลี่ยนเป็นสร้างดัชนีจากไฟล์ TSV ต้นฉบับโดยตรงแล้วบีบอัดด้วย zstd จากนั้นค่อยแตกไฟล์ทุกครั้งใน wasm วิธีนี้เร็วกว่า SQLite มาก
    ขนาดโมดูลก็ลดจาก 800KB เหลือ 52KB และถึงจะเปิดหลายอินสแตนซ์พร้อมกันก็ไม่เป็นภาระ
    สำหรับการค้นหาสตริง ผมใช้ stringzilla ซึ่งเร็วแบบเหลือเชื่อ
    SQLite ยอดเยี่ยม แต่ไม่ใช่คำตอบของทุกสถานการณ์

  • benchmark ของ SQLite ยัง optimize มาไม่มาก
    แค่เพิ่ม

    db.SetMaxOpenConns(runtime.NumCPU())
    db.SetMaxIdleConns(runtime.NumCPU())
    

    เท่านี้บนเครื่องผมประสิทธิภาพก็พุ่งจาก 27,700 r/s เป็น 89,687 r/s แล้ว
    ผมลองทั้ง prepared statement และเปลี่ยน timestamp เป็น int แต่แทบไม่ต่างมาก

  • บทความโอเค แต่ส่วนที่บอกว่า “DB ทุกตัวเข้าถึงไฟล์ซิสเต็มผ่าน open()” นั้นไม่แม่นยำนัก
    แอปอย่าง SQLite ใช้ mmap เพื่อแมปไฟล์เข้าไปในพื้นที่หน่วยความจำโดยตรง วิธีนี้ข้าม syscall และเข้าถึงได้เร็วกว่าเยอะ
    ช่วงหลังของบทความอธิบายการอ่านทั้งไฟล์เข้าหน่วยความจำ ซึ่งถ้าใช้ mmap น่าจะดีกว่า

    • จริงที่บทความอธิบาย IO ของ DB แบบเรียบง่ายเกินไป
      แต่ก็ไม่แน่ว่า mmap จะดีกว่าเสมอไป บางคนชอบจัดการเองในตรรกะของแอปมากกว่าพึ่ง OS API
      ดูงานวิจัยที่เกี่ยวข้องได้ที่ งานศึกษา mmap ของ CMU
    • backend store ที่ mmap ใช้อยู่สุดท้ายก็ยังเป็นไฟล์ในไฟล์ซิสเต็ม
      การพูดว่า “ทำงานเหมือน open()” อาจจะทำให้เรียบง่ายเกินไป แต่ในเชิงเทคนิคก็ถือว่าพูดได้ไม่ผิด
  • นานมาแล้วผมเคยทำเว็บแอปขายของเล็ก ๆ ด้วย Perl แต่เพราะบนเซิร์ฟเวอร์ของ ISP ติดตั้งอะไรไม่ได้เลยต้องใช้ file-based hash
    ลูกค้าใช้มันแบบเดิมต่อมาเกิน 20 ปีจนเสียชีวิต แล้วครอบครัวรับช่วงต่อและเปลี่ยนไปใช้ Wordpress
    ตอนที่เช็กครั้งสุดท้ายมีออเดอร์หลายแสนรายการแล้ว แต่ประสิทธิภาพก็ยังโอเค
    ด้วยพัฒนาการของฮาร์ดแวร์ โครงสร้างแบบแฮ็ก ๆนี้เลยอยู่ได้นานกว่าที่คิด ถ้าเป็นตอนนี้ SQLite ก็น่าจะพอแล้ว

    • อยากรู้ว่าเว็บไซต์นั้นขายสินค้าอะไร
  • ถ้าลองลงมือทำ storage เอง จะเข้าใจได้ว่าฐานข้อมูลทำงานอย่างไร
    คุณต้องจัดการดัชนีและโครงสร้างข้อมูลให้มีประสิทธิภาพ และสุดท้ายก็จะได้ข้อสรุปว่า “ถ้าไม่ได้ทำเล่น ๆ ก็ควรใช้ DB ตั้งแต่แรก”

  • Relational Databases Aren’t Dinosaurs, They’re Sharks
    เมื่อเทียบกับประโยชน์เล็กน้อยที่ได้จากแอปขนาดเล็กแล้ว เวลาที่เสียไปกับการประดิษฐ์ล้อขึ้นมาใหม่ นั้นมากกว่ามาก

    • อุปมาเรื่องฉลามกับไดโนเสาร์นี่เหมาะมาก
      ตั้งแต่ยุคครีเทเชียส ฉลามก็มีรูปร่างเกือบเหมือนทุกวันนี้แล้ว และหลังจากนั้นก็รอดมาได้โดยแทบไม่เปลี่ยนแปลง
      ในทางกลับกัน ไดโนเสาร์ เทอโรซอร์ และโมซาซอรัสหายไปหมด แต่ฉลาม จระเข้ และงูขนาดใหญ่ยังคงอยู่แทบเหมือนเดิมจนถึงตอนนี้เพราะเป็นการออกแบบที่ถูกปรับเหมาะแล้ว
      ผมคิดว่าฐานข้อมูลเชิงสัมพันธ์ก็เป็นแบบนั้น
  • ผมสนุกกับการอ่านบทความแบบนี้
    แต่ถึงอย่างนั้น 99% ของกรณีผมก็ยังใช้ DB ที่มี SQL และ transaction
    อย่างไรก็ตาม ช่วงหลังในโปรเจกต์ส่วนตัว ผมลองจัดการข้อมูลด้วยไฟล์ YAML บนไฟล์ซิสเต็มแบบง่าย ๆ และสำหรับสเกลของผมก็ไม่มีปัญหาเรื่องประสิทธิภาพเลย
    ความที่มนุษย์อ่านได้และทำ diff ได้ สำคัญกว่าประสิทธิภาพสำหรับผม
    แต่โดยมากแล้วผมก็ยังจะเลือก DB ที่มี query language และรับประกันความสอดคล้องแน่นอน

  • สุดท้ายแล้วเราก็มักต้องการฟีเจอร์ของ DB และการรับประกันแบบ ACID อยู่ดี
    ทุกครั้งที่ต้องไปใช้ legacy flat-file store ผมต้องเหนื่อยกับการพยายามยัดเรื่องความสอดคล้อง transaction และ query language เข้าไป สุดท้ายก็คือการประดิษฐ์ล้อขึ้นมาใหม่

  • ทันทีที่ต้องการ atomicity DB ก็กลายเป็นสิ่งจำเป็น
    การทำ atomic write บนไฟล์ซิสเต็มนั้นเปราะบางมาก
    ด้วยเหตุนี้ DB หลายตัวจึงเคยมีปัญหาเรื่องข้อมูลเสียหายเวลาเกิด crash อย่าง RocksDB บน Windows เมื่อก่อนก็เป็นแบบนั้น

    • ถ้าต้องการแก้ไขแบบอะตอมมิกกับไฟล์ ผมคงใช้ SQLite ไปเลย
      การทำเองให้ถูกต้องมันให้ความรู้สึกเหมือนเรื่องบ้าบอ ควรเรียนรู้วิธีเขียนให้ปลอดภัยผ่าน OS API ก็จริง แต่ทุกวันนี้มันเป็นทักษะเฉพาะทางเกินไป
      แถมคนที่มารับช่วงต่อก็มีโอกาสสูงที่จะดูแลต่อไม่ไหว สุดท้ายก็ต้องย้ายไป DB อยู่ดี
    • โค้ดในบทความนั้น ถ้าวันหนึ่งไฟดับขึ้นมาก็คงเหลือเป็นไฟล์ว่าง
      อย่างน้อยก็ควรเขียนลงไฟล์ชั่วคราวในไฟล์ซิสเต็มเดียวกัน แล้ว fsync ก่อนค่อย replace ด้วย rename
    • ถ้าเป็นกรณีง่าย ๆ ก็ไม่ได้เปราะบางขนาดนั้น
      ถ้าเขียนทั้ง DB ลงไฟล์ชั่วคราวแล้ว flush ก่อนค่อย move ไปทับ บน Unix ถือว่าเป็นอะตอมมิก
      แต่แนวทางนี้สเกลไม่ได้เลย ทุกการอัปเดตเล็ก ๆ ก็ต้องเขียนทั้งไฟล์ใหม่ และยังต้องจัดการ lock ด้วย มันแก้ได้แค่บางส่วนของ ACID
    • มองแบบนี้ก็ถือว่าคุณกำลังจัดการ A ใน ACID อยู่แล้ว
      อนึ่ง DuckDB ซึ่งเป็น OLAP DB ก็ทำงานกับ workload แบบ out-of-core ได้ยอดเยี่ยม
    • ณ ปี 2025 Linux + ext4 รองรับการเขียนแบบอะตอมมิกทั้งบล็อกเดี่ยวและหลายบล็อกแล้ว
      ลิงก์เอกสารทางการ
 
mstorm 14 일 전

ถึงจะอยู่ได้โดยไม่มีตู้เย็น แต่ก็คงไม่สะดวกใช่ไหมครับ
ในเมื่อใช้ตู้เย็นได้ ก็ไม่มีเหตุผลที่จะไม่ใช้มัน

 
foobarman 13 일 전

หมายความว่าคุณเป็นพวกอิลเบหรือเปล่า

 
alfenmage 6 일 전

ถ้าตอบว่าไม่ ก็เป็น Ilbe กันหมดเลยเหรอ? ฉันเป็นคนคย็องซังโดนะ?

 
foobarman 5 일 전

อยากรายงานแต่ไม่รู้วิธีรายงาน เฮ้อ.

 
okxrr 13 일 전

ดูเหมือนว่าคอมเมนต์นี้จะสะท้อนทั้งกรอบความคิดที่ปิดกั้นของนักพัฒนาชาวเกาหลีและระดับของ GeekNews ได้เป็นอย่างดี

 
alfenmage 6 일 전

ระดับนั้นคือระดับแบบไหนกันแน่ เหตุผลที่คุณประเมินระดับนั้นคืออะไร ลองพูดมาโดยใช้มากกว่า 2 อย่างจากตรรกะ/ข้อเท็จจริง/วิทยาศาสตร์/สถิติดูสิ อืออ

 
foobarman 5 일 전

ฮ่าๆ แค่ดูจากคำที่ใช้ก็รู้แล้วว่าเป็นพวกจาก DC Inside, Ilbe, Ppomppu/FCM แนวๆ นั้น อย่าไปใส่ใจเลย