- การทดลองเปรียบเทียบประสิทธิภาพโดยเก็บ ข้อมูล Delta Lake ขนาด 650GB บน S3 และประมวลผลในสภาพแวดล้อมแบบโหนดเดียวด้วย Polars, DuckDB, Daft, Spark
- ตรวจสอบว่า แต่ละเอนจินสามารถจัดการข้อมูลขนาดใหญ่ได้หรือไม่ บน EC2 อินสแตนซ์ที่มีหน่วยความจำ 32GB พร้อมสำรวจความเป็นไปได้ของโหนดเดียวเมื่อเทียบกับ Spark แบบคลัสเตอร์
- DuckDB ใช้เวลา 16 นาที, Polars ใช้เวลา 12 นาที, Daft ใช้เวลา 50 นาที, และ PySpark ใช้เวลามากกว่า 1 ชั่วโมง แสดงให้เห็นถึงความเป็นไปได้ในการประมวลผลจริงแม้อยู่บนโหนดเดียว
- Polars ยังไม่รองรับ Deletion Vector ขณะที่มีเพียง DuckDB ที่รองรับฟีเจอร์นี้ จึงมีความต่างด้าน ความเข้ากันได้กับ Lake House
- โดยสรุป การทดลองนี้พิสูจน์ว่า เฟรมเวิร์กแบบโหนดเดียวสามารถประมวลผลข้อมูลขนาดใหญ่ได้แม้บนฮาร์ดแวร์ต้นทุนต่ำ และชวนให้ทบทวนการพึ่งพา distributed computing
ความเหนื่อยล้าจากคลัสเตอร์และทางเลือกแบบโหนดเดียว
- เมื่อ ต้นทุนและความซับซ้อนของการดูแลคลัสเตอร์ Lake House แบบ SaaS เพิ่มขึ้น จึงมีการกล่าวถึงปรากฏการณ์ ‘cluster fatigue’
- ในอดีตแทบไม่มีทางเลือกนอกจาก Pandas จึงต้องใช้ Spark แต่การมาของ DuckDB·Polars·Daft(D.P.D.) ทำให้การประมวลผลแบบโหนดเดียวเป็นไปได้มากขึ้น
- D.P.D. สามารถจัดการ ชุดข้อมูลที่ใหญ่กว่าหน่วยความจำ (LTM) และทำ การคำนวณความเร็วสูง ได้
- บทความนี้เสนอทั้งทางเลือกแบบกระจายและไม่กระจาย พร้อมเน้นแนวคิด “Single Node Rebellion”
การตั้งค่าสภาพแวดล้อมการทดลอง
- สร้างตาราง Delta Lake บน S3 และจัดเก็บข้อมูลประมาณ 650GB (เดิมตั้งเป้า 1TB แต่หยุดไว้ก่อน)
- รัน DuckDB, Polars, Daft บน EC2 อินสแตนซ์ (RAM 32GB, CPU 16 คอร์) แล้วเปรียบเทียบกับ Spark
- ข้อมูลเป็น ข้อมูลจำลองในรูปแบบโพสต์โซเชียลมีเดีย โดยสร้าง Python dict แปลงเป็น Daft DataFrame แล้วบันทึกเป็นไฟล์ Parquet
- จากนั้นแปลงไฟล์ Parquet เป็น ตาราง Delta Lake บน Databricks พร้อมแบ่งพาร์ทิชันตามปีและเดือน
- เมื่อตัด Delta log ออก พบว่ามีข้อมูลประมาณ 650GB
ข้อจำกัดด้านหน่วยความจำและความจำเป็นของการสตรีมมิง
- เนื่องจากต้องประมวลผลข้อมูล 650GB บนโหนดเดียวที่มีหน่วยความจำ 32GB จึงเกิดประเด็นเรื่อง ความจำเป็นของการรันคิวรีแบบสตรีมมิง
- มีการอ้างถึง GitHub issue ของ Polars ซึ่งสะท้อนความต้องการ ฟีเจอร์เขียนแบบสตรีมมิงสำหรับ Iceberg
- บทความเน้นย้ำว่าเฟรมเวิร์กยุคใหม่อย่าง Polars และ DuckDB ควรมี การรองรับพื้นฐานสำหรับการอ่านและเขียนฟอร์แมต Lake House แบบสตรีมมิง
ผลการทดสอบของแต่ละเอนจิน
- DuckDB
- เป็นตัวเดียวที่รองรับ Deletion Vector
- ประมวลผลข้อมูล 650GB บนเครื่องลินุกซ์ 32GB ได้สำเร็จในเวลาเพียง 16 นาที
- โค้ดเรียบง่ายและสร้างไฟล์ผลลัพธ์ได้ตามปกติ
- Polars
- ไม่รองรับ Deletion Vector จึงมีข้อจำกัดในสภาพแวดล้อม Lake House
- จำเป็นต้องใช้ Lazy API (Scan/Sink)
- ประมวลผลเสร็จใน 12 นาที เร็วกว่า DuckDB
- Daft
- พัฒนาด้วย Rust ใช้งานได้ดี แต่ ใช้เวลา 50 นาที ช้าที่สุด
- ยืนยันได้ว่าทำงานได้เสถียรในงานที่เกี่ยวข้องกับ Iceberg
- PySpark (Databricks Single Node)
- ใช้เวลามากกว่า 1 ชั่วโมง โดยรันแบบไม่ปรับแต่ง
- มีประสิทธิภาพต่ำกว่าเมื่อเทียบกับเอนจินแบบโหนดเดียว
- เป้าหมายของการทดลองครั้งนี้ไม่ใช่เรื่องความเร็ว แต่คือ การพิสูจน์ความเป็นไปได้ของโหนดเดียว
บทสรุปและนัยสำคัญ
- การทดลองนี้พิสูจน์ว่า เฟรมเวิร์กแบบโหนดเดียวสามารถประมวลผลข้อมูล Lake House ขนาดใหญ่ได้
- แม้เป็นฮาร์ดแวร์ต้นทุนต่ำ ก็ยังได้ เวลาในการรันที่สมเหตุสมผลและโครงสร้างโค้ดที่เรียบง่าย
- DuckDB, Polars, Daft ต่างก็ให้ ประสิทธิภาพระดับใช้งานจริงได้โดยไม่ต้องพึ่งคลัสเตอร์แบบกระจาย
- สิ่งนี้แสดงให้เห็นว่า distributed computing ไม่ใช่คำตอบเดียวเสมอไป และชวนให้ทบทวนสถาปัตยกรรม Lake House ยุคใหม่
- แนวคิด “Single Node Rebellion” ชี้ให้เห็นถึงความเป็นไปได้ของแนวทาง data engineering ที่คุ้มค่ากว่า
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
Daft เป็น เอนจินประมวลผลข้อมูลประสิทธิภาพสูง สำหรับเวิร์กโหลด AI ที่ทำงานได้ทั้งบนโหนดเดี่ยวและสภาพแวดล้อมแบบกระจาย
เบนช์มาร์กครั้งนี้ทำให้เราเห็นโอกาสในการปรับปรุงด้าน ความขนาน และ pipelining อีกมาก โดยเฉพาะในตัวอ่าน deltalake และตัวดำเนินการ groupby ที่ยังมีจุดให้ปรับแต่งได้มาก
เราวางแผนจะสะท้อนการปรับปรุงเหล่านี้ในรีลีสถัดไป และดูรายละเอียดเพิ่มเติมได้ที่ GitHub, Twitter, LinkedIn
ถ้าสนใจ Daft ก็ลองใช้เองได้ด้วย
pip install daftแทนที่จะใช้ tooling ที่เกินความจำเป็น ก็ใช้เครื่องมือ GNU ธรรมดาก็พอ
อ้างอิงไว้ว่าเป็นบทความเก่าแต่ยังน่าสนใจ — command-line tools can be 235x faster than your Hadoop cluster
ถ้าลอง aggregate ข้อมูล JSON ขนาด 650GB ด้วยเครื่องมือ CLI ก็คงยากจะตาม ประสิทธิภาพการประมวลผลแบบขนาน ของ DuckDB หรือ ClickHouse ให้ทัน ฉันเคยลองกับ GNU Parallel แล้วแต่ก็มีขีดจำกัด
ในงานจริงจำเป็นต้องมี data catalog และงานที่ทำบนคลัสเตอร์
ฉัน query โดย ไล่อ่านไฟล์ Parquet โดยตรง แทนที่จะใช้ Delta หรือ Iceberg
ฉันดึงผลลัพธ์ที่ query จาก BigQuery ลงมาเป็นไฟล์ Parquet บนเครื่อง (ราว 1GB ต่อไฟล์) แล้ววิเคราะห์ด้วย DuckDB มันทำงานได้ดีแม้ข้อมูลจะใหญ่กว่า RAM มาก
บางครั้งฉันยังเปรียบเทียบ ประสิทธิภาพการ aggregate ของ BigQuery กับ DuckDB แล้วแบ่งงานไปรันบนสองเอนจิน นี่เป็นส่วนที่สนุกของ data engineering
ด้วยแบนด์วิดท์สูงสุด 10Gbps ของอินสแตนซ์ c5.4xlarge อย่างน้อยก็ต้องใช้ 9 นาทีในการอ่าน 650GB จาก S3
ความต่างเล็กน้อยในวิธีทำ I/O scheduling น่าจะส่งผลต่อผลลัพธ์อย่างมาก
อันที่จริงการใช้อินสแตนซ์ใหญ่กว่านี้เพื่อให้จบเร็วอาจ คุ้มค่ากว่า ด้วยซ้ำ
NVMe storage เร็วกว่า S3 มาก และ CPU 8~16 คอร์บนเครื่องก็อาจดีกว่าคลาวด์ได้
S3 เป็นผลิตภัณฑ์ที่ยอดเยี่ยม แต่ยังสู้ ประสิทธิภาพของสตอเรจบนเครื่อง ไม่ได้
การกระจายขนาดไฟล์หรือความเบ้ของ API call น่าจะเป็นตัวแปรที่ใหญ่กว่า
และฉันเห็นด้วยเต็มที่กับประเด็นที่ว่า “อินสแตนซ์ใหญ่กว่าอาจจบงานได้ถูกกว่า”
Spark เหมาะกับชุดข้อมูลขนาดใหญ่หลายขั้นตอน และเมื่อใช้ S3 เป็นแบ็กเอนด์ คอขวดด้านเครือข่าย ก็จะสะท้อนออกมาเป็นต้นทุน
ประสิทธิภาพบนโหนดเดียวของ DuckDB/Polars น่าประทับใจ แต่ก็เหมือน เอาเครื่องบินบนรันเวย์มาแข่งกับมอเตอร์ไซค์
ความต่างแบบนี้เองที่ทำให้หลายคนรู้สึกล้ากับ distributed computing
ถ้ารู้ขีดจำกัดของทรัพยากรและแสดงประสิทธิภาพจริงเป็นสัดส่วนเทียบกับเพดานนั้น ภาพจะชัดขึ้นมาก
การลองหลายระบบถือว่าเป็นเรื่องดี แต่ก็อยากให้พูดถึง query ที่ใหญ่เกินหน่วยความจำ แบบจริงจังกว่านี้
DuckDB แข็งแรงมากเรื่องการสตรีมเมื่อข้อมูลเกินหน่วยความจำ แต่ Polars ยังไม่ค่อยสุกงอมในจุดนี้
ค่าตั้งต้นของ S3 ไม่ได้ขัดขวางการอ่านแบบขนาน ดังนั้นคอขวดก็น่าจะเป็น แบนด์วิดท์เครือข่ายของ VM ในที่สุด
ClickHouse เร็วที่สุด ส่วน DuckDB ดีที่สุดในแง่ ความเรียบง่ายและเสถียรภาพ
Flink และ PySpark ช้ากว่า 3~5 เท่า ส่วน Dask กับ Ray ก็ช้าเกินไป
ตอนนี้ฉันแนะนำให้เริ่มจาก DuckDB หรือ ClickHouse สำหรับเวิร์กโหลดส่วนใหญ่ และเมื่อ Pandas ช้าเกินไปก็แทนที่ด้วย DuckDB นี่คือกลยุทธ์พื้นฐานของฉัน
แม้จะเป็นไลบรารีแบบโหนดเดียว ก็ยังจัดการข้อมูลระดับ 1TB ได้สบาย และค่อยขยับไปใช้ Spark เมื่อเกิน 10TB
อีเวนต์ที่เกี่ยวข้อง
แต่หลายกรณีก็แก้ได้ด้วยเครื่องมือที่ดีกว่า
ก่อนหน้านี้เคยมีวิศวกรจูเนียร์ใช้ การต่อสตริง Python เพื่อจัดการ JSON ขนาด 5GB หลายร้อยไฟล์จนใช้เวลา 18 ชั่วโมง แต่
พอเปลี่ยนเป็นเครื่องมือคอนโซลง่าย ๆ กับ multiprocessing ก็ลดเหลือ 35 นาที
หัวใจสำคัญคือ การเลือกเครื่องมือให้เหมาะสม
ค่าดูแลรักษาและค่าใช้งานต่ำมาก เป็น เครื่องมือที่คุ้มค่าคุ้มราคา
เพื่อแก้ปัญหาที่มีไฟล์ Parquet มากเกินไปเมื่อเขียนแบบ batch เล็ก ๆ DuckLake จึงเก็บข้อมูลนั้นแบบ inline ไว้ใน DBMS (เช่น Postgres)
เพิ่งมีความสามารถเขียนกลับเป็น Parquet ได้เมื่อไม่นานนี้ แต่ตอนนี้ยังต้องการการทำให้เสถียรอีก
เอกสารที่เกี่ยวข้อง
เพราะต้องแทนแค็ตตาล็อกด้วย SQL DB แต่ข้อดีของ Parquet ก็คือหลีกเลี่ยงความซับซ้อนแบบนั้นได้
ถ้าทำแค็ตตาล็อกให้เป็น Parquet-based ด้วย ก็ดูน่าจะกลายเป็น ฟอร์แมตที่บูตสแตรปตัวเองได้