- แพลตฟอร์มการชำระเงินของ Uber มีข้อมูลบัญชีแยกประเภทที่สะสมมาตั้งแต่ปี 2017 เติบโตเกิน 1 ล้านล้านรายการ และมีขนาดระดับหลาย PB จึงย้ายจากโครงสร้างผสมระหว่าง DynamoDB·TerraBlob·LedgerStore ไปสู่โครงสร้างที่ใช้ LedgerStore เป็นศูนย์กลาง
- เนื่องจากภาระต้นทุนของ DynamoDB โครงสร้างเดิมที่เก็บข้อมูลล่าสุดไว้เพียง 12 สัปดาห์จึงถูกแทนที่ด้วย LedgerStore ซึ่งเป็นสตอเรจแบบบัญชีแยกประเภทชนิด append-onlyในฐานะคำตอบระยะยาว
- การตรวจสอบใช้ทั้งshadow validation ที่จำลองทราฟฟิกโปรดักชัน และการตรวจสอบออฟไลน์ที่เปรียบเทียบ full dump เพื่อแยกประเมินความเสี่ยงของข้อมูลปัจจุบันและข้อมูล cold data
- เนื่องจาก backfill อาจสร้างโหลดสูงกว่าทราฟฟิกปกติ จึงค่อย ๆ ดำเนินการด้วยแบตช์ขนาดเล็ก, ความเป็น idempotent, การควบคุมความเร็ว, การหยุดฉุกเฉิน และการแยกเรคอร์ดที่มีปัญหา
- การสลับระบบถูก rollout อย่างระมัดระวังตลอดหลายสัปดาห์ และปิดงานแบบไร้ downtime ตั้งแต่ fallback ระยะแรก การเก็บข้อมูลใน DynamoDB ต่ออีกหนึ่งเดือน ไปจนถึงการสำรองข้อมูลครั้งสุดท้ายและลบตาราง
เป้าหมายของการย้ายและโครงสร้างการจัดเก็บเดิม
- แพลตฟอร์มการชำระเงิน Gulfstream ของ Uber ใช้ DynamoDB เป็นสตอเรจตั้งแต่เปิดตัวในปี 2017
- เมื่อค่าใช้จ่ายของ DynamoDB สูงขึ้นในระดับของ Uber โครงสร้างการจัดเก็บจึงแยกออกเป็นสามส่วน
- hot data ล่าสุด 12 สัปดาห์เก็บไว้ใน DynamoDB
- cold data ที่เก่ากว่าเก็บไว้ใน TerraBlob ซึ่งเป็น blob store ภายในของ Uber
- มีการเขียนข้อมูลลง LedgerStore อยู่แล้ว และท้ายที่สุดมันก็กลายเป็นเป้าหมายของการย้ายครั้งนี้
- ขอบเขตการย้ายคือข้อมูลบัญชีแยกประเภทของทุกธุรกิจใน Uber ตั้งแต่ปี 2017 เป็นต้นมา
- เรคอร์ดแบบ immutable: 1.2PB หลังบีบอัด
- ดัชนีรอง: 0.5PB แบบไม่บีบอัด
- เรคอร์ดบัญชีแยกประเภทเมื่อเขียนแล้วแทบไม่สามารถเปลี่ยนแปลงได้ แต่หากต้องแก้ปัญหา ข้อมูลดัชนีรองยังสามารถแก้ไขได้
เหตุผลที่เลือก LedgerStore
- LedgerStore เป็นฐานข้อมูลสไตล์บัญชีแยกประเภทแบบ append-only
- การออกแบบที่เหมาะกับข้อมูลด้านการชำระเงินสอดคล้องกับความต้องการของ Gulfstream
- immutability ที่ตรวจสอบได้ ซึ่งยืนยันได้ด้วยลายเซ็นเข้ารหัสว่าเรคอร์ดถูกแก้ไขหรือไม่
- tiered storage ที่แยก hot data และ cold data ตามลักษณะการให้บริการคำขอและต้นทุนการจัดเก็บ
- คุณสมบัติด้าน latency ที่ดีกว่าสำหรับดัชนีรองที่มี eventual consistency
- การลดสตอเรจจากสามระบบเหลือหนึ่งเดียวช่วยให้โค้ดการเข้าถึงสตอเรจและการออกแบบการสร้างดัชนีของ Gulfstream เรียบง่ายขึ้น
- LedgerStore ทำงานแบบ on-premises ภายในดาต้าเซ็นเตอร์ของ Uber จึงให้ network latency ที่เร็วกว่าได้
- การย้ายไป LedgerStore ยังช่วยลดต้นทุนแบบเกิดซ้ำในระยะยาวได้มาก
ความเสถียรของทราฟฟิกปัจจุบันที่ยืนยันด้วย shadow validation
- เพื่อประเมินว่า backfill ถูกต้องหรือไม่ มีการกำหนดเกณฑ์ไว้ห้าข้อ
- ความครบถ้วน: มีการ backfill เรคอร์ดทั้งหมด
- ความถูกต้อง: ทุกเรคอร์ดถูกต้อง
- โหลด: LedgerStore สามารถรองรับโหลดปัจจุบันได้
- latency: ค่า P99 latency ของ LedgerStore อยู่ในช่วงที่ยอมรับได้
- index lag: ความล่าช้าในการสร้างดัชนีรองแบบเบื้องหลังอยู่ในช่วงที่ยอมรับได้
- shadow validation เปรียบเทียบผลตอบกลับจากสตอเรจเดิมกับผลตอบกลับเมื่อใช้ LedgerStore เป็นแหล่งข้อมูล
- เป้าหมายคือให้ความครบถ้วนและความถูกต้องของ backfill ตามเกณฑ์ shadow validation อยู่ที่อย่างน้อย 99.99% โดยกำหนดเพดานไว้ที่ 99.9999%
- เหตุผลที่ต้องมีเพดานคือ หากตรวจสอบทุกกรณีต้องสงสัยจนสุดในการยืนยันข้อมูลขนาดใหญ่ โครงการอาจหยุดชะงักได้
- การย้ายข้อมูลเก่าอาจมีทั้งการเขียนผิดพลาดตั้งแต่ช่วงพัฒนาแรกเริ่ม หรือข้อมูลเสียหายตามขนาดระบบปะปนอยู่
- แม้ S3 จะรับประกัน durability ระดับ 11 nines แต่ที่ระดับ 1 ล้านล้านเรคอร์ด ก็ยังคาดว่าจะมีข้อมูลเสียหายได้ราว 10 รายการ
- ในดัชนีแบบ eventual consistency อาจเกิดfalse positive ที่เรคอร์ดซึ่งจะปรากฏในอีกไม่กี่วินาทีถูกมองว่าเป็นข้อมูลหายในการตรวจแบบ shadow
- หากต้องการยืนยัน 6 nines อย่างน่าเชื่อถือ ต้องเปรียบเทียบ 100 ล้านรายการ และถ้าเทียบได้ 1,000 รายการต่อวินาที ก็ต้องเก็บข้อมูลเกินหนึ่งวัน
- ส่วน 7 nines ต้องรอ 12 วันภายใต้เงื่อนไขเดียวกัน
- การจำลองทราฟฟิกโปรดักชันไปยัง LedgerStore ทำให้สามารถตรวจสอบทั้งโหลด, latency, index lag และความน่าเชื่อถือของโค้ดเข้าถึงข้อมูลไปพร้อมกัน
- ปัญหา latency และ index lag ที่พบระหว่างการย้าย นำไปสู่การปรับปรุงหลายอย่าง
- การปรับ partition key ให้เหมาะสม เพื่อกระจายข้อมูลดัชนีให้ดีขึ้น
- แก้ปัญหาดัชนีที่ทำให้เกิดการสแกนเรคอร์ดแทน point lookup
- shadow validation แบบ live มีประโยชน์กับข้อมูลที่ถูกเข้าถึงอยู่ในปัจจุบัน แต่ให้การรับประกันที่เข้มแข็งได้ยากกับข้อมูลเก่าเกือบทั้งหมดที่แทบไม่ถูกใช้งาน
การตรวจสอบออฟไลน์และ incremental backfill
- การตรวจสอบออฟไลน์เปรียบเทียบข้อมูลทั้งหมดใน LedgerStore กับ data dump จาก DynamoDB
- เนื่องจากทราฟฟิก live ส่วนใหญ่เข้าถึงข้อมูลล่าสุด ปัญหาที่ซ่อนอยู่ใน cold data จึงยากจะตรวจพบด้วย shadow validation เพียงอย่างเดียว
- เรคอร์ดที่มีปัญหาด้านข้อมูลต้องถูกข้ามไปเพื่อให้ backfill ดำเนินต่อได้ และต้องคำนึงถึงความเป็นไปได้ที่งาน backfill เองอาจมีบั๊กด้วย
- งานตรวจสอบที่ใหญ่ที่สุดใช้ข้อมูลขนาด 70TB หลังบีบอัด ประเมินเป็น 300TB แบบไม่บีบอัด และเปรียบเทียบ 760 พันล้านเรคอร์ด ในงานเดียว
- งาน Apache Spark ขนาดนี้จำเป็นต้องมี data shuffle โดยใช้ Distributed Shuffle as a Service for Spark, Dynamic Resource Allocation และ Speculative Execution ร่วมกัน
- เรคอร์ดที่หายไปซึ่งพบจากการตรวจสอบออฟไลน์ถูกนำมาใช้เป็นอินพุตของ incremental backfill
- มีการทำซ้ำระหว่างการตรวจสอบและ backfill เพื่อยืนยันว่าได้เขียนเรคอร์ดครบทั้งหมด
ปัญหาด้านปฏิบัติการที่พบระหว่าง backfill
- backfill ต้องเริ่มจากขนาดเล็กและค่อย ๆ ขยายจนถึงขีดจำกัดของระบบ
- หากฝืนดันโหลดเกินขีดจำกัดแบบไม่ยั้ง ก็เท่ากับยิง DDoS ใส่ระบบของตัวเอง
- ต้องหาคอขวด แก้ไข แล้วจึงค่อยขยายอีกครั้ง
- หลังการขยายแต่ละครั้งต้องมีการมอนิเตอร์อย่างใกล้ชิด
- การ backfill ข้อมูลหลายปีภายในไม่กี่เดือนทำให้เกิดโหลดสูงกว่าทราฟฟิกปกติมาก
- หากโปรดักชันรองรับได้ 1,000 รายการต่อวินาที แล้ว backfill ข้อมูล 100 พันล้านเรคอร์ดที่ 10,000 รายการต่อวินาที ก็ยังต้องใช้เวลา 120 วัน
- หากมีความเป็นไปได้ว่างาน backfill จะทำให้เกิด incident ต้องหยุดทันที
- backfill ไม่ควรเป็นงานที่วิ่งยาวรวดเดียวจนจบ แต่ควรถูกแบ่งเป็นincremental batch
- แต่ละ batch ควรเล็กพอที่จะจบได้ภายในไม่กี่นาที
- เนื่องจากงานอาจหยุดกลาง batch ได้ จึงต้องเป็น idempotent
- เมื่อ batch จบ ควรบันทึกสถิติ เช่น จำนวนเรคอร์ดที่อ่าน และจำนวนเรคอร์ดที่ backfill ลงไฟล์ เพื่อนำไป aggregate และติดตามความคืบหน้า
- backfill ที่ปลอดภัยต้องมีการควบคุมความเร็วที่ปรับได้
- ใน Java/Scala สามารถใช้ Guava
RateLimiterได้ - หากสามารถรันได้เร็วขึ้นในช่วงที่ทราฟฟิกโปรดักชันต่ำ ก็ให้ปรับ RPS โดยติดตามสถานะของระบบ
- Uber ปรับ RPS ด้วยวิธี additive increase/multiplicative decrease แต่ยังคงมีเพดานไว้เพื่อความปลอดภัย
- ใน Java/Scala สามารถใช้ Guava
- หากสงสัยว่ามีความขัดข้องหรือโอเวอร์โหลด ต้องสามารถหยุด backfill ได้อย่างรวดเร็ว
- ระหว่าง incident ควรหยุด backfill เพื่อเป็นมาตรการป้องกันและลด noise
- แม้หลัง incident ผ่านไปแล้ว กระบวนการฟื้นตัวของระบบก็อาจสร้างโหลดเพิ่มได้
- ความสามารถในการหยุดฉุกเฉินยังช่วยในการดีบักปัญหาที่เกี่ยวกับสเกลได้ด้วย
ไฟล์ขนาดใหญ่, fault tolerance และ logging
- ควรรักษาขนาดไฟล์ data dump ไว้ราว 1GB และยืดหยุ่นได้ประมาณ 10 เท่าทั้งสองด้าน
- หากไฟล์ใหญ่เกินไป อาจติดข้อจำกัด MultiPart ของหลายเครื่องมือ
- หากไฟล์เล็กเกินไป จำนวนไฟล์จะมากจนแม้แต่การดึงรายการไฟล์ก็ใช้เวลานานมาก
- เมื่อต้องรันคำสั่ง shell อาจชนข้อจำกัด ARGMAX ได้
- ในกระบวนการแปลงข้อมูลของ backfill ย่อมเกิดปัญหาคุณภาพข้อมูลหรือเรคอร์ดเสียหายอย่างหลีกเลี่ยงไม่ได้
- เรคอร์ดที่มีปัญหากระจายแบบสุ่ม จึงไม่สามารถหยุดงานทุกครั้งได้
- ขณะเดียวกันก็ไม่ควรมองข้าม เพราะอาจเป็นบั๊กในโค้ดได้เช่นกัน
- เรคอร์ดที่มีปัญหาถูก dump แยกต่างหากและมอนิเตอร์สถิติไว้
- หากอัตราความล้มเหลวสูง ต้องหยุด backfill ด้วยตนเอง แก้ปัญหา แล้วค่อยทำต่อ
- การเขียนเรคอร์ดอาจล้มเหลวเพราะ RPC timeout
- แม้จะ retry ได้ แต่ถึงจุดหนึ่งก็ต้องยอมข้ามต่อไปไม่ว่าเหตุผลจะเป็นอะไร เพื่อให้งานโดยรวมเดินหน้าต่อได้
- แม้อยากเก็บ log จำนวนมากเพื่อดีบักและตรวจสอบความคืบหน้า แต่ก็อาจสร้างแรงกดดันสูงต่อโครงสร้างพื้นฐานด้าน logging
- ต่อให้เขียน log ได้ ปริมาณที่ต้องเก็บรักษาก็อาจมากเกินไป
- ส่วนที่สร้าง log จำนวนมากจึงต้องใช้rate limit
- หาก error เกิดขึ้นน้อยมาก ก็อาจเก็บ log ของ error ทั้งหมดไว้ได้
gradual rollout และการถอด fallback
- การสลับไปใช้ LedgerStore ลดความเสี่ยงด้วย rollout แบบระมัดระวัง นอกเหนือจากการตรวจสอบและการวิเคราะห์สถิติ backfill
- rollout ดำเนินต่อเนื่องหลายสัปดาห์ พร้อมการอนุมัติจากวิศวกร on-call ของบริการผู้เรียกใช้หลัก
- ในระยะแรกมีการใช้fallback โดยหากหาไม่พบข้อมูลใน LedgerStore ก็จะไปดึงจาก DynamoDB
- ทุกเรคอร์ดที่ถูกบันทึกว่า missing ใน fallback log จะถูกตรวจซ้ำว่าใน LedgerStore ขาดหายจริงหรือไม่
- หลังจากถอด fallback แล้ว ข้อมูลใน DynamoDB ยังถูกเก็บไว้อีกหนึ่งเดือน
- จากนั้นจึงหยุดการเขียนลง DynamoDB สร้าง backup สุดท้าย แล้วลบตาราง
- การย้ายทั้งหมดใช้เวลา 2 ปี และเสร็จสิ้นโดยไม่มี downtime หรือ incident ทั้งระหว่างและหลังการย้าย
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
สงสัยว่าจะสามารถเอาข้อมูล 1.7 เพตะไบต์ (เรคคอร์ดที่ทำดัชนีไว้ 1 ล้านล้านรายการ) ใส่ไว้ใน bare-metal server ที่แรงมากเครื่องเดียวซึ่งมีค่าใช้จ่ายเพียงไม่กี่พันดอลลาร์ต่อเดือนหรือน้อยกว่านั้น แล้วให้บริการด้วย SQLite ได้หรือไม่
ตัวอย่างเช่นแนวทางแบบนี้: https://use.expensify.com/blog/scaling-sqlite-to-4m-qps-on-a...
SQLite รองรับฐานข้อมูล ได้สูงสุด 281 เทราไบต์ โดยตั้งอยู่บนสมมติฐานว่าคุณสามารถหาดิสก์และไฟล์ซิสเต็มที่รองรับไฟล์ขนาด 281 เทราไบต์ได้ ถึงอย่างนั้นก็ยังระบุว่า หากเริ่มมีแนวโน้มว่าขนาดเนื้อหาจะโตถึงระดับเทราไบต์ ก็ควรพิจารณาฐานข้อมูลแบบรวมศูนย์ client/server มากกว่า SQLite
ดูแล้วคงยากที่จะยัดพื้นที่เก็บข้อมูลขนาดนี้ไว้ในเซิร์ฟเวอร์เครื่องเดียว และยิ่งยากกว่าถ้าจะให้เหลือค่าใช้จ่ายแค่ไม่กี่พันดอลลาร์ต่อเดือน SQLite เองก็ไม่เหมาะกับงานนี้ด้วย
ถ้าบริษัทมีทุนและศักยภาพองค์กรเพียงพอ ก็สามารถสร้างคลาวด์ของตัวเองได้ถูกกว่ามาก แต่ส่วนสำคัญของการคำนวณก็คือการจ้างภายนอกให้รับความเสี่ยงเหล่านั้นแทน
[0] https://www.sqlite.org/releaselog/3_33_0.html
[1] https://www.sqlite.org/limits.html (#12)
ดูเหมือนว่า LedgerStore จะไม่ใช่โอเพนซอร์ส [1] และถ้าจะหาข้อมูลที่เกี่ยวข้องต้องไล่อ่านโพสต์ในบล็อกของ Uber ที่ลิงก์ย้อนหากันไปมา
ในบรรดาบทความจากปี 2021 ดูเหมือนชิ้นนี้จะมีข้อมูลเกี่ยวกับ LedgerStore มากที่สุด:
https://www.uber.com/en-US/blog/dynamodb-to-docstore-migrati...
[1]:https://github.com/uber
โดยรวมแล้ว Uber ดูเป็นบริษัทที่มีแนวโน้ม สร้างเอง สูง พวกเขามักสรุปว่าโซลูชันโอเพนซอร์สที่มีอยู่ยังไม่พอ แล้วจึงลงมือสร้างเอง ต่างจากแนวทางของ Facebook ที่ปรับปรุง MySQL ด้วย MyRocks/RocksDB และคงความเป็นโอเพนซอร์สไว้
อ่านบทความแล้วจะเห็นว่า Uber ใช้ DynamoDB ผิดตั้งแต่ค่อนข้างเร็ว
ดูเหมือนว่าบาง user journey หลักต้องการ strong consistency และธุรกรรมในอดีตก็ต้องการ data warehousing ปริมาณมาก
แปลกเหมือนกันที่พวกเขาไม่ได้เปลี่ยนโครงสร้าง DynamoDB แบบ 2 ตารางไปเป็นโครงแบบ DynamoDB + Redshift ก่อน ซึ่งเป็นแพตเทิร์นที่พบได้ค่อนข้างบ่อย
ราวปี 2015 เป็นช่วงที่บริษัทเทคเท่ ๆ อย่าง Netflix, Spotify, SoundCloud, Uber สร้างเครื่องมืออินฟราและฐานข้อมูลกันเยอะมาก
ทุกวันนี้วิศวกรมักพูดกันด้วยศัพท์ของ AWS/คลาวด์
เลยรู้สึกสดใหม่ดีที่ยังมีองค์กรที่สร้างเครื่องมือพวกนี้เองอยู่
ไม่แน่ใจเรื่องความคุ้มค่าของโปรเจ็กต์นี้โดยเฉพาะ แต่ DynamoDB แพงจริง ๆ
ช่วงหนึ่งผมเคยคิดว่าคนอื่นแค่ใช้ DynamoDB ผิดทั้งหมด เพราะไปสแกนและคิวรีแทนที่จะทำ point lookup บนตารางที่คำนวณไว้ล่วงหน้า
แต่ถึงจะใช้มันเหมือน distributed hash table ก็ยังต้องจ่ายพรีเมียมก้อนใหญ่อยู่ดี
RCU 1 หน่วยอ่านได้สูงสุด 4KB ดังนั้นถ้าจะอ่าน 100MB ต้องใช้ 100,000 RCU ซึ่งเท่ากับปีละ 30,000 ดอลลาร์ หรือเดือนละ 2,500 ดอลลาร์ ถ้าผมคำนวณไม่ผิด ก็ไม่เห็นมีอะไรที่ราคาใกล้เคียงนี้เลย
สงสัยว่าพวกเขาได้พิจารณา https://tigerbeetle.com หรือไม่
และ Uber ก็น่าจะเป็นหนึ่งในบริษัทยักษ์ใหญ่ไม่กี่แห่งที่มีสัญญาสนับสนุนกับ Zig Foundation
ขอแสดงความยินดีกับคนที่มีส่วนร่วมในงานนี้ แต่แค่ค่าใช้จ่ายในการดูแลทีมนี้ก็น่าจะสูงมากและแทบไม่ต่างจากเงินที่ประหยัดได้ 6 ล้านดอลลาร์ แถมยังมีภาระการบำรุงรักษาเพิ่มเข้ามาอีก
อีกทั้งระบบชำระเงินก็ดูไม่น่าจะเป็นเดิมพันระยะยาวนัก เลยน่าสนใจว่าทำไมทีมถึงรับโปรเจ็กต์แบบนี้ เป็น ต้นทุนจม แบบหนึ่งที่เกิดจากการมีทีมวิศวกรรมอยู่แล้วหรือเปล่า?
ระหว่างสองขั้วนี้ยังมีพื้นที่มากพอสำหรับการประเมินต้นทุนที่สมจริงกว่า
ถ้าข้อมูลกับดัชนีมีขนาด 1.7PB ก็จะอยู่ราว 5.1 ล้านดอลลาร์ต่อปีตามราคาปกติของ storage บน DynamoDB
มันดูสมจริงพอที่จะมีระบบเฉพาะทางที่ออกแบบมาให้เหมาะกับส่วนสำคัญของธุรกิจ
ไม่ได้เป็นงานใหญ่เท่าที่หลายคนพูดกัน และเพราะเรคคอร์ดเป็นแบบ immutable หลายอย่างจึงง่ายขึ้นมาก
สงสัยว่านี่เป็นอีกหนึ่งกรณีพิเศษที่เมื่อถึงสเกลระดับหนึ่งแล้ว การสร้างเองจะคุ้มกว่าหรือไม่ สเกลที่ Uber ต้องรองรับนั้นน่าทึ่งมาก
จากบทความต้นฉบับเพียงอย่างเดียว ยังไม่ชัดว่าต้นทุนรวมในการเป็นเจ้าของของบริการที่รีแฟกเตอร์ใหม่นี้เป็นเท่าไร ตอนนี้พวกเขาต้องดูแลทั้งฐานข้อมูลของตัวเองและ storage ด้านหลังมันด้วยไม่ใช่หรือ หรือผมพลาดอะไรไป?
บริษัทนั้นไม่ได้ขายผลิตภัณฑ์สำหรับผู้ใช้ปลายทาง แต่ขาย distributed file system เป็นผลิตภัณฑ์
ผมคิดว่าบริษัทส่วนใหญ่ไม่มีความเชี่ยวชาญพอจะสร้างระบบอย่างฐานข้อมูลได้ และถึงแม้ในเชิงต้นทุนการพัฒนาจะดูน่าทำ แต่ในทางปฏิบัติพวกเขากลัวงานแบบนี้กันมาก
ผมมองว่านี่เป็นตัวอย่างที่ดีมากว่าระบบเก็บข้อมูลแบบ คลาวด์ที่เป็นกรรมสิทธิ์ อาจแพงได้แค่ไหน และการย้ายออกไปยังอย่างอื่นก็เป็นสิ่งที่ทำได้จริงในทางปฏิบัติ
หากสมมติว่าผู้คนตัดสินใจอย่างมีเหตุผล ดูเหมือนกำลังจะถึงเวลา คิดบัญชี กับผู้ให้บริการคลาวด์แล้ว
ผมเคยรับงานสัญญาที่บริษัทเล็กแห่งหนึ่ง ซึ่งใช้ GCP Bigtable เพื่อรันรายงานจากข้อมูลที่มาจากฐานข้อมูล MySQL ขนาด 375MB และจ่ายมากกว่า 11,000 ดอลลาร์ต่อเดือน
พวกเขาจ้าง data scientist ที่เพิ่งเรียนจบมาทำรายงาน และเขากำลังทำงานอย่างไร้ประสิทธิภาพแบบเหลือเชื่อกับชุดข้อมูลที่เล็กมาก พอผมบอกให้แก้พรุ่งนี้เลยด้วยเงินเล็กน้อย เขาก็ปฏิเสธ
มันเป็นแค่ ระบบที่ออกแบบผิด ถ้าคุณเอาฐานข้อมูล on-premises มาจัดสรรทรัพยากรเกินจริงอย่างมหาศาลเพื่อทำงานเดียวกัน ก็จะเกิดปัญหาแบบเดียวกันอยู่ดี