8 คะแนน โดย GN⁺ 2025-11-16 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การทดลองเปรียบเทียบประสิทธิภาพโดยเก็บ ข้อมูล 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 ความคิดเห็น

 
GN⁺ 2025-11-16
ความคิดเห็นจาก Hacker News
  • ฉันเป็นวิศวกรซอฟต์แวร์ที่ทำงานอยู่ที่ Eventual และอยากขอบคุณที่แชร์เบนช์มาร์กของ Daft ที่ทีมของเราสร้างขึ้น
    Daft เป็น เอนจินประมวลผลข้อมูลประสิทธิภาพสูง สำหรับเวิร์กโหลด AI ที่ทำงานได้ทั้งบนโหนดเดี่ยวและสภาพแวดล้อมแบบกระจาย
    เบนช์มาร์กครั้งนี้ทำให้เราเห็นโอกาสในการปรับปรุงด้าน ความขนาน และ pipelining อีกมาก โดยเฉพาะในตัวอ่าน deltalake และตัวดำเนินการ groupby ที่ยังมีจุดให้ปรับแต่งได้มาก
    เราวางแผนจะสะท้อนการปรับปรุงเหล่านี้ในรีลีสถัดไป และดูรายละเอียดเพิ่มเติมได้ที่ GitHub, Twitter, LinkedIn
    ถ้าสนใจ Daft ก็ลองใช้เองได้ด้วย pip install daft
    • สงสัยว่ามีแผนจะ เปิด Daft เป็นแบ็กเอนด์ของ ibis หรือไม่ ถ้าเป็นเช่นนั้นก็น่าจะดีต่อการทดสอบโดยสลับจากเอนจินอื่นได้อย่างลื่นไหล
    • อันนี้ดูเหมือนเป็นบัญชีที่สร้างมาเพื่อโปรโมตบริษัท
  • Awk? มีบทความที่น่าสนใจเกี่ยวข้องอยู่ — Command-line tools can be 235x faster than your Hadoop cluster
  • 650GB นี่เล็กจนใส่มือถือฉันได้เลย
    แทนที่จะใช้ tooling ที่เกินความจำเป็น ก็ใช้เครื่องมือ GNU ธรรมดาก็พอ
    อ้างอิงไว้ว่าเป็นบทความเก่าแต่ยังน่าสนใจ — command-line tools can be 235x faster than your Hadoop cluster
    • ตอนนี้มันต่างจาก ยุค Hadoop ปี 2014 ที่บทความนั้นพูดถึงแล้ว
      ถ้าลอง aggregate ข้อมูล JSON ขนาด 650GB ด้วยเครื่องมือ CLI ก็คงยากจะตาม ประสิทธิภาพการประมวลผลแบบขนาน ของ DuckDB หรือ ClickHouse ให้ทัน ฉันเคยลองกับ GNU Parallel แล้วแต่ก็มีขีดจำกัด
    • ถ้าเป็น 650TB เรื่องก็จะต่างไปโดยสิ้นเชิง บทความนั้นเป็นแค่ microbenchmark
      ในงานจริงจำเป็นต้องมี data catalog และงานที่ทำบนคลัสเตอร์
    • มีการแชร์วิดีโอนี้ พร้อมมุกว่า “ลืมไปแล้วว่าตัวเลขเล็กขนาดนั้นนับยังไง”
  • ฉันมักใช้ DuckDB จัดการ ‘biggish data’ บนโหนดเดียว
    ฉัน query โดย ไล่อ่านไฟล์ Parquet โดยตรง แทนที่จะใช้ Delta หรือ Iceberg
    ฉันดึงผลลัพธ์ที่ query จาก BigQuery ลงมาเป็นไฟล์ Parquet บนเครื่อง (ราว 1GB ต่อไฟล์) แล้ววิเคราะห์ด้วย DuckDB มันทำงานได้ดีแม้ข้อมูลจะใหญ่กว่า RAM มาก
    บางครั้งฉันยังเปรียบเทียบ ประสิทธิภาพการ aggregate ของ BigQuery กับ DuckDB แล้วแบ่งงานไปรันบนสองเอนจิน นี่เป็นส่วนที่สนุกของ data engineering
    • ระดับ 650GB นี่จัดการบน local filesystem ได้สบายอยู่แล้ว ไม่ต้องใช้เครื่องมือซับซ้อน
  • เบนช์มาร์กครั้งนี้ดูเหมือนเป็นการทดลองที่ถูกครอบงำโดย แบนด์วิดท์ของ NIC อย่างสมบูรณ์
    ด้วยแบนด์วิดท์สูงสุด 10Gbps ของอินสแตนซ์ c5.4xlarge อย่างน้อยก็ต้องใช้ 9 นาทีในการอ่าน 650GB จาก S3
    ความต่างเล็กน้อยในวิธีทำ I/O scheduling น่าจะส่งผลต่อผลลัพธ์อย่างมาก
    อันที่จริงการใช้อินสแตนซ์ใหญ่กว่านี้เพื่อให้จบเร็วอาจ คุ้มค่ากว่า ด้วยซ้ำ
    • น่าจะสนุกถ้าลองทดสอบบนเดสก์ท็อปทั่วไปหรือโน้ตบุ๊กดี ๆ ด้วย
      NVMe storage เร็วกว่า S3 มาก และ CPU 8~16 คอร์บนเครื่องก็อาจดีกว่าคลาวด์ได้
      S3 เป็นผลิตภัณฑ์ที่ยอดเยี่ยม แต่ยังสู้ ประสิทธิภาพของสตอเรจบนเครื่อง ไม่ได้
    • Query จริงอาจไม่ได้สแกนไฟล์ทั้งหมด แต่ใช้ S3 byte-range reads เพื่อประมวลผลเฉพาะบางคอลัมน์มากกว่า
      การกระจายขนาดไฟล์หรือความเบ้ของ API call น่าจะเป็นตัวแปรที่ใหญ่กว่า
      และฉันเห็นด้วยเต็มที่กับประเด็นที่ว่า “อินสแตนซ์ใหญ่กว่าอาจจบงานได้ถูกกว่า”
    • คุณค่าของการทดลอง ยังไม่ชัดเจน
      Spark เหมาะกับชุดข้อมูลขนาดใหญ่หลายขั้นตอน และเมื่อใช้ S3 เป็นแบ็กเอนด์ คอขวดด้านเครือข่าย ก็จะสะท้อนออกมาเป็นต้นทุน
      ประสิทธิภาพบนโหนดเดียวของ DuckDB/Polars น่าประทับใจ แต่ก็เหมือน เอาเครื่องบินบนรันเวย์มาแข่งกับมอเตอร์ไซค์
    • 10Gbps นี่ต่ำเกินไป ที่ Google เขาใช้ NIC 400Gbps และ การควบคุม TCP congestion ที่ปรับปรุงแล้ว
      ความต่างแบบนี้เองที่ทำให้หลายคนรู้สึกล้ากับ distributed computing
    • เห็นด้วยกับข้อสังเกตนี้ มีบทเรียนที่ได้เรียนมาจากวอลล์สตรีตเมื่อ 30 ปีก่อน — ก่อนทดสอบประสิทธิภาพของระบบ ต้องเข้าใจเพดานทางทฤษฎีก่อน
      ถ้ารู้ขีดจำกัดของทรัพยากรและแสดงประสิทธิภาพจริงเป็นสัดส่วนเทียบกับเพดานนั้น ภาพจะชัดขึ้นมาก
  • บทความนี้เป็น งานเขียนที่ทำให้เข้าใจผิด อยู่สองด้าน
    1. ในความเป็นจริงน่าจะมีการทำ column pruning ทำให้เข้าถึงเพียง 2 คอลัมน์ + metadata เท่านั้น
    2. เวลาส่วนใหญ่น่าจะติดอยู่กับ S3 I/O และ ข้อจำกัดจำนวนการเชื่อมต่อพร้อมกัน น่าจะส่งผลมากกว่า
      การลองหลายระบบถือว่าเป็นเรื่องดี แต่ก็อยากให้พูดถึง query ที่ใหญ่เกินหน่วยความจำ แบบจริงจังกว่านี้
    • สิ่งสำคัญคือ query นี้เป็น projection ที่คืนค่ามาเพียงบางส่วนจากทั้ง 650GB
      DuckDB แข็งแรงมากเรื่องการสตรีมเมื่อข้อมูลเกินหน่วยความจำ แต่ Polars ยังไม่ค่อยสุกงอมในจุดนี้
      ค่าตั้งต้นของ S3 ไม่ได้ขัดขวางการอ่านแบบขนาน ดังนั้นคอขวดก็น่าจะเป็น แบนด์วิดท์เครือข่ายของ VM ในที่สุด
  • ช่วงหลังฉันต้องจัดการข้อมูล JSON หลาย TB และปัญหาคือมี ไฟล์เล็กขนาด 10~20MB จำนวนมาก
    ClickHouse เร็วที่สุด ส่วน DuckDB ดีที่สุดในแง่ ความเรียบง่ายและเสถียรภาพ
    Flink และ PySpark ช้ากว่า 3~5 เท่า ส่วน Dask กับ Ray ก็ช้าเกินไป
    ตอนนี้ฉันแนะนำให้เริ่มจาก DuckDB หรือ ClickHouse สำหรับเวิร์กโหลดส่วนใหญ่ และเมื่อ Pandas ช้าเกินไปก็แทนที่ด้วย DuckDB นี่คือกลยุทธ์พื้นฐานของฉัน
    • สงสัยว่าคุณแปลงข้อมูล JSON ไปเป็นฟอร์แมตอื่นก่อนหรือเปล่า หรือว่า ทำงานบน JSON โดยตรง เลย
  • Polars พึ่งพา delta-rs สำหรับการรองรับ Delta Lake และ implementation นี้ยังไม่รองรับ Deletion vectors
    แม้จะเป็นไลบรารีแบบโหนดเดียว ก็ยังจัดการข้อมูลระดับ 1TB ได้สบาย และค่อยขยับไปใช้ Spark เมื่อเกิน 10TB
    อีเวนต์ที่เกี่ยวข้อง
    • หลายคนย้ายไปใช้ Spark เร็วเกินไปเพียงเพราะคิดว่า “Spark ทำ parallelization ได้ง่าย”
      แต่หลายกรณีก็แก้ได้ด้วยเครื่องมือที่ดีกว่า
      ก่อนหน้านี้เคยมีวิศวกรจูเนียร์ใช้ การต่อสตริง Python เพื่อจัดการ JSON ขนาด 5GB หลายร้อยไฟล์จนใช้เวลา 18 ชั่วโมง แต่
      พอเปลี่ยนเป็นเครื่องมือคอนโซลง่าย ๆ กับ multiprocessing ก็ลดเหลือ 35 นาที
      หัวใจสำคัญคือ การเลือกเครื่องมือให้เหมาะสม
  • Presto (AWS Athena) อาจเป็นทางเลือกที่เร็วและดีกว่า และฉันก็อยากลองทดสอบข้อมูล 650GB บนเครื่องตัวเองเหมือนกัน
    • ตอนนี้ Presto เปลี่ยนชื่อเป็น Trino แล้ว
      ค่าดูแลรักษาและค่าใช้งานต่ำมาก เป็น เครื่องมือที่คุ้มค่าคุ้มราคา
  • ฟอร์แมตแค็ตตาล็อก DuckLake ใหม่ของ DuckDB ก็น่าจะเป็นผู้เข้าทดสอบที่ดีเช่นกัน — ducklake.select
    • ฟีเจอร์ data inlining flush ของ DuckLake ยังอยู่ในขั้นอัลฟา
      เพื่อแก้ปัญหาที่มีไฟล์ Parquet มากเกินไปเมื่อเขียนแบบ batch เล็ก ๆ DuckLake จึงเก็บข้อมูลนั้นแบบ inline ไว้ใน DBMS (เช่น Postgres)
      เพิ่งมีความสามารถเขียนกลับเป็น Parquet ได้เมื่อไม่นานนี้ แต่ตอนนี้ยังต้องการการทำให้เสถียรอีก
      เอกสารที่เกี่ยวข้อง
    • ฟอร์แมต DuckLake มี ปัญหาไก่กับไข่จากการพึ่งพา SQL
      เพราะต้องแทนแค็ตตาล็อกด้วย SQL DB แต่ข้อดีของ Parquet ก็คือหลีกเลี่ยงความซับซ้อนแบบนั้นได้
      ถ้าทำแค็ตตาล็อกให้เป็น Parquet-based ด้วย ก็ดูน่าจะกลายเป็น ฟอร์แมตที่บูตสแตรปตัวเองได้