Cloudflare D1 หรือ Turso: อ่านฟรีมากกว่า ไม่ได้แปลว่าย้ายระบบง่ายกว่า

|ผู้เขียน: กองบรรณาธิการ QUASA|4 นาทีในการอ่าน
Cloudflare D1 หรือ Turso: อ่านฟรีมากกว่า ไม่ได้แปลว่าย้ายระบบง่ายกว่า

Turso ให้โควตาอ่านในแผนฟรีมากกว่า Cloudflare D1 แต่ถ้าแอปทำงานบน Cloudflare Workers ทั้งหมด D1 มีโควตาอ่านในแผนจ่ายเงินสูงและเชื่อมต่อผ่าน binding ได้ตรงจุด ส่วนแอปที่ต้องทำงานบนหลายรันไทม์ควรให้น้ำหนักกับไดรเวอร์ของ Turso มากขึ้น เพราะโควตาที่มากกว่าไม่ได้ช่วยย้ายโค้ดเชื่อมต่อฐานข้อมูลให้เอง

คำตอบขึ้นอยู่กับทั้งตำแหน่งที่รันแอปและลักษณะ SQL คำสั่งที่คืนผลลัพธ์หนึ่งแถวอาจอ่านเพียงไม่กี่แถวเมื่อใช้ดัชนี หรืออ่านเกือบทั้งตารางเมื่อค้นคอลัมน์ที่ไม่มีดัชนี ตัวเลข rows read จึงต้องอ่านคู่กับ rows written พื้นที่เก็บข้อมูล และค่า compute ของรันไทม์ที่รับคำขอ

โควตาฟรีและแผนจ่ายเงินต่างกันตรงไหน

ตารางราคา D1 ของ Cloudflare กำหนดให้ Workers Free อ่านได้ 5 ล้านแถวและเขียนได้ 100,000 แถวต่อวัน พร้อมพื้นที่รวม 5 GB ส่วน Workers Paid รวมการอ่าน 25 พันล้านแถวและการเขียน 50 ล้านแถวต่อรอบเดือน รวมพื้นที่ 5 GB แรก จากนั้นคิด $0.001 ต่อการอ่านเกินทุกล้านแถว $1 ต่อการเขียนเกินทุกล้านแถว และ $0.75 ต่อ GB ต่อเดือนสำหรับพื้นที่ส่วนเกิน ขีดจำกัดฟรีรีเซ็ตทุกวันตามเวลา UTC ขณะที่โควตาจ่ายเงินผูกกับรอบต่ออายุสมาชิก

ตารางราคา Turso แบบรายเดือน ระบุว่า Free อ่านได้ 500 ล้านแถว เขียนได้ 10 ล้านแถว และเก็บข้อมูลได้ 5 GB ต่อเดือน แผน Developer ราคา $5.99 ต่อเดือน รวมการอ่าน 2.5 พันล้านแถว การเขียน 25 ล้านแถว พื้นที่ 9 GB และการซิงก์ 10 GB ส่วน Scaler ราคา $29 ต่อเดือน รวมการอ่าน 100 พันล้านแถว การเขียน 100 ล้านแถว และพื้นที่ 24 GB ข้อสรุปเรื่องโควตาอ่านจึงเปลี่ยนตามแผน: Turso ได้เปรียบในระดับฟรี แต่ D1 Workers Paid รวมแถวอ่านมากกว่า Turso Developer ขณะที่ Turso Scaler ขยับสูงกว่าทั้งคู่

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

พื้นที่ 5 GB ที่เท่ากันในแผนฟรีก็ไม่ได้หมายถึงเก็บตารางข้อมูลหลักได้เท่ากันเสมอไป ดัชนีกินพื้นที่ด้วย และการออกแบบดัชนีอาจต่างกันตามรูปแบบคำสั่งของแต่ละแอป สำหรับงานที่ต้องซิงก์สำเนาในเครื่อง Turso ยังมีโควตาการซิงก์แยกจากพื้นที่และจำนวนแถว จึงควรนับข้อมูลที่ต้องส่งไปยังสำเนาเป็นต้นทุนอีกชนิดหนึ่ง ไม่ใช่รวมไว้ในช่อง rows read

SQL สามแบบเปลี่ยน rows read อย่างไร

คำสั่งค้น orders ผ่านดัชนีอ่านเพียงส่วนเล็กของตาราง ขณะที่คำสั่งไม่มีดัชนีต้องกวาดทั้งตาราง

rows read ของ D1 นับแถวที่คำสั่งอ่านระหว่างทำงาน ไม่ใช่จำนวนแถวที่ส่งกลับไปยังแอป การกรองคอลัมน์ที่ไม่มีดัชนีจึงอาจคืนผลลัพธ์แถวเดียวหลังจากตรวจแถวจำนวนมาก ตัวอย่างต่อไปนี้เป็นสถานการณ์สมมติสำหรับเห็นผลของแผนการค้นหา ไม่ใช่ผลทดสอบ: ตาราง orders มี 100,000 แถว และแต่ละคำสั่งถูกรัน 100,000 ครั้งต่อเดือน ค่า rows read ต่อครั้งเป็นค่าที่สมมติว่าได้จาก meta.rows_read ของ D1

  • ค้นด้วยคีย์หลัก: SELECT * FROM orders WHERE id = ? สมมติว่า meta.rows_read เท่ากับ 2 ต่อครั้ง แม้คืนคำสั่งซื้อเพียงหนึ่งแถว ยอดอ่านทั้งเดือนคือ 200,000 แถว วิธีค้นแบบนี้ใช้โควตาน้อยเพราะฐานข้อมูลเข้าถึงตำแหน่งข้อมูลได้ผ่านดัชนีของคีย์หลัก
  • ค้นกลุ่มผ่านดัชนี: SELECT * FROM orders WHERE customer_id = ? เมื่อมีดัชนีบน customer_id สมมติว่าคืนผลเฉลี่ย 200 แถว แต่ meta.rows_read เท่ากับ 250 ต่อครั้ง ยอดอ่านทั้งเดือนเป็น 25 ล้านแถว จำนวนแถวที่อ่านมากกว่าผลลัพธ์ได้ แม้แผนการค้นหาจะยังดีกว่าการกวาดตาราง
  • ค้นคอลัมน์ที่ไม่มีดัชนี: SELECT * FROM orders WHERE external_ref = ? สมมติว่าพบเพียงหนึ่งแถว แต่ต้องตรวจครบ 100,000 แถว ยอดอ่านจากความถี่เดียวกันจะเป็น 10 พันล้านแถวต่อเดือน ผลลัพธ์เล็กไม่ได้แปลว่าต้นทุนอ่านเล็ก

ความต่างระหว่าง 200,000 กับ 10 พันล้านแถวเกิดจากวิธีหาข้อมูล ไม่ได้เกิดจากจำนวนครั้งที่แอปเรียกฐานข้อมูล ในสมมตินี้ full scan ยังต่ำกว่าโควตาอ่านรายเดือนของ D1 Workers Paid แต่สูงกว่าโควตาฟรีของ Turso มาก หากจำนวนคำสั่งแบบ full scan เพิ่มเป็น 500,000 ครั้งโดยตารางยังมีขนาดเดิม ยอดอ่านตามสมมติจะเป็น 50 พันล้านแถว และส่วนที่เกินโควตา D1 Workers Paid จะคิดเป็น $25 ก่อนรวมค่า Workers กับพื้นที่ ตัวเลขนี้เป็นผลคูณจากสมมติฐาน ไม่ใช่ราคาที่แอปจริงทุกแห่งจะจ่าย

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

ตัวเลขสมมติของ D1 ไม่ควรถูกยกไปเป็นบิล Turso โดยตรง แม้ทั้งสองบริการแสดงหน่วย rows read เพราะตัวนับจริงขึ้นกับคำสั่ง ดัชนี และวิธีประมวลผลบนบริการที่เลือก ใน D1 ผลลัพธ์แต่ละคำสั่งมี meta.rows_read และ meta.rows_written สำหรับแทนค่าตัวอย่างด้วยภาระงานจริง ส่วนการตัดสินใจเลือกแผนควรใช้คำสั่งที่เกิดบ่อยและวันที่ทราฟฟิกสูงร่วมกัน ไม่ใช่ดูขนาดตารางหรือยอดเฉลี่ยเดือนเพียงค่าเดียว

ค่า D1 ต้องบวกค่า Workers อย่างไร

D1 ไม่คิดค่า compute ของฐานข้อมูลแยกตามเวลาที่เปิดใช้งาน แต่ Worker ที่รับคำขอ เรียกฐานข้อมูล และแปลงผลลัพธ์ยังมีต้นทุนของตัวเอง ตารางราคา Cloudflare Workers ระบุว่า Workers Paid มีค่าขั้นต่ำ $5 ต่อเดือน และในรูปแบบ Standard รวมคำขอ 10 ล้านครั้งกับเวลา CPU 30 ล้านมิลลิวินาทีต่อเดือน ก่อนคิดส่วนเกินตามจำนวนคำขอและเวลา CPU ดังนั้นคำว่าอ่าน D1 ได้อีกมากก่อนเสียค่าเกินโควตา ไม่ได้หมายความว่าการให้บริการแอปไม่มีค่า compute

ในตัวอย่างที่รัน SQL 100,000 ครั้งต่อเดือน ค่าแถวอ่านอาจยังอยู่ในโควตา D1 Workers Paid ทั้งสามแบบ แต่จำนวนคำสั่ง SQL ไม่เท่ากับจำนวนคำขอ HTTP เสมอไป คำขอหนึ่งอาจเรียกฐานข้อมูลหลายครั้ง หรือบางคำขออาจตอบจากแคชโดยไม่เรียกฐานข้อมูล การประเมิน Workers จึงต้องแยกจำนวนคำขอที่เข้าถึงโค้ดและเวลา CPU ออกจากจำนวนคำสั่ง SQL พร้อมดูงานอื่นใน Worker เช่น การตรวจสิทธิ์และการจัดรูปผลลัพธ์

ถ้าเลือก Turso ให้แอปที่ยังรันบน Workers ค่าสมาชิกหรือค่าใช้ Turso ไม่ได้แทนที่ค่า Workers ทั้งหมด แอปยังใช้รันไทม์เดิมเพื่อรับคำขอ และต้องส่งคำสั่งไปยังฐานข้อมูลตามวิธีเชื่อมต่อที่เลือก หากย้าย compute ไป Node.js หรือผู้ให้บริการรายอื่น ต้นทุน compute ก็ย้ายไปอยู่ในบิลของสภาพแวดล้อมนั้นด้วย ประเด็นนี้สำคัญเมื่อเลือกรันไทม์สำหรับฟังก์ชันของแอปควบคู่กับฐานข้อมูล

ย้ายรันไทม์ได้ ไม่ได้แปลว่าย้ายโค้ดได้ทันที

Turso มีไดรเวอร์สำหรับหลายภาษา ส่วนการเชื่อมต่อ D1 ของแอปบน Workers ใช้ binding

D1 สะดวกเมื่อโค้ดทำงานใน Workers เพราะแอปเรียกฐานข้อมูลผ่าน binding เช่น env.DB และใช้เมธอดสำหรับเตรียมกับรัน SQL การเปลี่ยนจาก Workers ไปยังรันไทม์อื่นจึงกระทบชั้นเชื่อมต่อที่อ้าง binding แม้ตารางและ SQL ส่วนใหญ่ยังดูคุ้นเคย การย้ายเฉพาะจุดรับคำขอออกไป แต่ยังคงฐานข้อมูล D1 ไว้ ก็ต้องออกแบบทางเข้าฐานข้อมูลและการยืนยันตัวตนใหม่

คู่มือ SDK ของ Turso แยกแพ็กเกจสำหรับฐานข้อมูลในเครื่อง การซิงก์ข้อมูล และการเชื่อมต่อฐานข้อมูลระยะไกลผ่าน HTTP โดยมีทางเลือกสำหรับ TypeScript, Python, Go และ Rust ไดรเวอร์แบบ serverless ใช้งานในเซิร์ฟเวอร์ ฟังก์ชันแบบ serverless และ edge runtime ที่รองรับภาษานั้นได้ ความยืดหยุ่นนี้มีประโยชน์เมื่อ API เบื้องหลัง งานตามกำหนดเวลา และบริการอื่นไม่ได้รันอยู่บนแพลตฟอร์มเดียวกัน

อย่างไรก็ตาม Turso มีทางเลือกของ engine และไดรเวอร์ที่ต้องจับคู่ให้ถูก ฐานข้อมูล Turso ที่เข้าถึงผ่านเครือข่ายใช้กลุ่ม serverless driver ส่วนฐานข้อมูล libSQL ระยะไกลใช้กลุ่ม libSQL client แอปที่ใช้ ORM ควรดูว่า ORM นั้นเชื่อมกับไดรเวอร์ใดอยู่ก่อน เพราะการเปลี่ยนแพ็กเกจอาจแตะชนิดข้อมูล วิธีส่งคำสั่ง และการจัดการผลลัพธ์ แม้ SQL ที่แอปเขียนจะยังใช้ได้

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

Replica ของสองบริการแก้ปัญหาคนละแบบ

D1 กระจายสำเนาสำหรับอ่านผ่าน Sessions API ส่วน Turso รองรับสำเนาในเครื่องที่ซิงก์กับฐานข้อมูล

คู่มือ read replication ของ D1 อธิบายว่าสำเนาสำหรับอ่านกระจายไปตามภูมิภาค ส่วนคำสั่งเขียนยังส่งไปฐานข้อมูลหลัก และแอปต้องใช้ Sessions API จึงจะอ่านจาก replica ได้ หากไม่ใช้ API นี้ คำสั่งยังทำงานที่ฐานข้อมูลหลัก การมี replica จึงไม่ได้ทำให้คำขออ่านทุกครั้งถูกส่งไปยังสำเนาที่ใกล้ผู้ใช้โดยอัตโนมัติ

สำเนาของ D1 รับข้อมูลจากฐานข้อมูลหลักแบบไม่พร้อมกัน จึงอาจตามหลังการเขียนล่าสุด Sessions API ใช้ลำดับข้อมูลภายในเซสชันเพื่อไม่ให้การอ่านครั้งถัดไปย้อนกลับไปเห็นข้อมูลเก่ากว่าที่เซสชันเคยเห็น แอปที่ต้องเห็นผลการเขียนล่าสุดตั้งแต่คำสั่งแรกยังต้องเลือกรูปแบบเริ่มเซสชันให้เหมาะ การอ่านผ่าน replica ไม่เพิ่มค่าบริการแยกสำหรับตัวสำเนา แต่ยังนับ rows read และ rows written ของคำสั่งตามปกติ

Turso มีทางเลือกอีกแบบคือฐานข้อมูลในเครื่องที่ซิงก์กับคลาวด์ ซึ่งทำให้แอปอ่านจากสำเนาใกล้กระบวนการของตัวเองได้ รูปแบบ Turso Sync ใช้การส่งและดึงการเปลี่ยนแปลงอย่างชัดเจน ส่วน embedded replica บน libSQL เป็นอีกแนวทางที่อ่านในเครื่องและส่งงานเขียนไปฐานข้อมูลหลัก สองทางเลือกนี้มีภาระเรื่องสถานะข้อมูลและสภาพแวดล้อมที่เก็บสำเนาแตกต่างกัน จึงไม่ควรเทียบกับ replica ของ D1 จากคำว่าอ่านใกล้ผู้ใช้อย่างเดียว

ถ้าแอปอยู่บน Workers ทั้งหมด การใช้ Sessions API ของ D1 ทำให้การอ่านจาก replica อยู่ในทางเชื่อมต่อเดิมของแอป แต่ถ้าแอปมีหลายรันไทม์หรือมีส่วนที่ทำงานใกล้ข้อมูลในเครื่อง Turso เปิดทางออกแบบสำเนาในฝั่งแอปมากกว่า ประโยชน์ที่ได้ขึ้นกับความถี่ในการซิงก์ ความสดของข้อมูลที่ยอมรับได้ และข้อจำกัดของแต่ละรันไทม์ ไม่ได้ตามมาจากจำนวน replica เพียงอย่างเดียว

เลือกตามตำแหน่งแอปและภาระงาน

  • แอปอยู่บน Workers ทั้งหมด: เริ่มเทียบ D1 กับรูปแบบ SQL จริง โดยเฉพาะคำสั่งอ่านบ่อยและคอลัมน์ที่ต้องทำดัชนี binding ลดงานเชื่อมต่อในสภาพแวดล้อมนี้ และโควตาอ่านของ Workers Paid ใหญ่กว่าแผนจ่ายเงินระดับเริ่มต้นของ Turso มาก แต่ต้องรวมค่าขั้นต่ำและการใช้คำขอกับ CPU ของ Workers ด้วย
  • แอปทำงานหลายรันไทม์หรือมีแผนย้าย compute: ให้ Turso เป็นตัวเลือกหลักสำหรับการประเมินไดรเวอร์ระยะไกล แล้วดูว่าชั้นเชื่อมต่อที่แอปใช้อยู่ย้ายตามได้มากเพียงใด โควตาฟรีที่มากกว่าช่วยเรื่องปริมาณอ่าน แต่ไม่ชดเชยงานแก้การยืนยันตัวตน ORM หรือรูปแบบซิงก์ข้อมูลที่เลือกไว้
  • แอปต้องอ่านจากสำเนาใกล้จุดทำงาน: เลือกจากรูปแบบความสอดคล้องของข้อมูลก่อนราคา D1 ใช้ replica ภายในบริการผ่าน Sessions API ขณะที่สำเนาในเครื่องของ Turso เพิ่มการควบคุมและหน้าที่ซิงก์ให้แอป ต้องประเมินว่ารันไทม์เก็บสำเนาได้อย่างไรและยอมรับข้อมูลที่ตามหลังฐานข้อมูลหลักได้แค่ไหน

สำหรับการตัดสินใจที่มีผลต่อบิลมากที่สุด ให้จับคู่คำสั่ง SQL ที่รันบ่อยกับจำนวนครั้งในวันที่ยุ่งและตลอดเดือน แล้วแยกยอดอ่าน ยอดเขียน ขนาดตารางรวมดัชนี และค่า compute ออกจากกัน หากผลต่างเกิดจาก full scan การปรับดัชนีอาจเปลี่ยนข้อสรุปเรื่องแผนราคาได้ หากผลต่างเกิดจากจำนวนรันไทม์ที่ต้องรองรับ ต้นทุนย้ายชั้นเชื่อมต่ออาจสำคัญกว่าโควตาอ่านที่เหลืออยู่

อ่านเพิ่มเติม:

แชร์:

สมัครรับจดหมายข่าวของเรา

รับข่าวสารล่าสุดเกี่ยวกับ Web3, AI และคริปโตส่งตรงถึงกล่องจดหมายของคุณ

0