- F3(Future-proof File Format) คือฟอร์แมตสตอเรจแบบคอลัมน์โอเพนซอร์สรุ่นถัดไป โดยมีการทำงานร่วมกันได้ ความสามารถในการขยาย และประสิทธิภาพเป็นหลักการออกแบบสำคัญ เพื่อ ขจัดความจำเป็นในการสร้างฟอร์แมตใหม่ทุกครั้งที่สภาพแวดล้อมด้านการประมวลผลข้อมูลและคอมพิวต์เปลี่ยนแปลงไป
- แต่ละไฟล์ F3 มีโครงสร้างแบบ self-describing โดยฝังทั้งข้อมูล เมทาดาทา และแม้แต่ ตัวถอดรหัสไบนารี WebAssembly(Wasm) เอาไว้ ทำให้รับประกันความเข้ากันได้บนทุกแพลตฟอร์มแม้ไม่มีตัวถอดรหัสแบบเนทีฟ
- มี เลย์เอาต์สตอเรจที่มีประสิทธิภาพ ซึ่งรวมเทคนิคการเข้ารหัสสมัยใหม่ เช่น staircase compression และ vectorized decoding พร้อมปรับปรุงปัญหาเลย์เอาต์ของ Parquet และ ORC ด้วยการแยกหน่วย I/O หน่วยการเข้ารหัส และหน่วยพจนานุกรมออกจากกัน
- ผ่าน Decoding API แบบปลั๊กอิน และกลไกการฝัง Wasm นักพัฒนาสามารถเพิ่มสคีมการเข้ารหัสใหม่ได้อย่างง่ายดาย และสามารถอ่านไฟล์ทุกไฟล์ได้โดยไม่ขึ้นกับเวอร์ชันของไลบรารี จึงช่วยแก้ปัญหาการทำงานร่วมกันของ Parquet
- ผลการประเมินพิสูจน์ทั้งประสิทธิภาพของเลย์เอาต์สตอเรจ F3 และข้อดีของการถอดรหัสด้วย Wasm โดยมีสตอเรจโอเวอร์เฮดเพียงระดับกิโลไบต์ และ ประสิทธิภาพที่ลดลงของการถอดรหัสด้วย Wasm อยู่ที่ 10~30% เมื่อเทียบกับเนทีฟ ซึ่งถือว่ายอมรับได้
ภูมิหลังและแรงจูงใจ
ข้อจำกัดของฟอร์แมตแบบคอลัมน์เดิม
- Parquet และ ORC ถูกพัฒนาขึ้นในช่วงต้นทศวรรษ 2010 สำหรับระบบวิเคราะห์ข้อมูลอย่าง Hive, Impala และ Spark และช่วยให้สามารถแชร์ข้อมูลระหว่าง data warehouse และ data lake ได้
- หลังผ่านไป 10 ปี งานวิจัยในปัจจุบันแสดงให้เห็นว่าฟอร์แมตเหล่านี้ยังไม่เพียงพอสำหรับการวิเคราะห์ข้อมูลสมัยใหม่ เนื่องจากอิงอยู่บน สมมติฐานด้านประสิทธิภาพฮาร์ดแวร์ที่ล้าสมัย และ สมมติฐานเกี่ยวกับรูปแบบการเข้าถึงของเวิร์กโหลด ในยุคที่ออกแบบ
- ตลอด 10 ปีที่ผ่านมา ประสิทธิภาพของสตอเรจและเครือข่ายเพิ่มขึ้นหลายสิบเท่า แต่ CPU ไม่ได้เพิ่มขึ้นในอัตราเดียวกัน ทำให้ระบบติดคอขวดที่ การคอมพิวต์ มากกว่า I/O
- การเติบโตของ data lake ทำให้ข้อมูลจำนวนมากขึ้นถูกเก็บไว้บนคลาวด์สตอเรจที่แบนด์วิดท์สูงแต่มี latency สูง เช่น Amazon S3
- แอปพลิเคชันไม่ได้เก็บเพียงข้อมูลแบบตารางที่มีคอลัมน์จำนวนน้อยอีกต่อไป ในเวิร์กโหลด ML การเก็บตารางขนาดกว้างที่มี หลายพันคอลัมน์, vector embedding มิติสูง และ blob ขนาดใหญ่ เช่น รูปภาพและวิดีโอ กลายเป็นเรื่องปกติ
- ความต้องการทำ random access หรืออัปเดตก็เพิ่มขึ้นเช่นกัน แต่ฟอร์แมตเดิมไม่เหมาะกับรูปแบบการใช้งานเหล่านี้
- แม้ว่าความก้าวหน้าด้านการบีบอัด การทำดัชนี และการกรองในช่วงหลังจะพยายามแก้ข้อบกพร่องเหล่านี้ แต่ ฟอร์แมตไฟล์เดิมไม่ได้ถูกออกแบบมาให้ขยายได้ง่าย
- ต่อให้เพิ่มฟีเจอร์ใหม่เข้าไป ก็ยากจะคาดหวังให้มี Parquet และ ORC เวอร์ชันล่าสุดในทุก implementation ที่กระจายอยู่ในหลายภาษา
- ระบบที่ใช้ไลบรารีเวอร์ชันเก่าอาจถอดรหัสเนื้อหาของไฟล์ใหม่ไม่ได้ ทำให้ระบบส่วนใหญ่รองรับได้แค่ ฟีเจอร์ที่เป็นตัวหารร่วมต่ำสุด เพื่อหลีกเลี่ยงปัญหาการทำงานร่วมกัน
การเกิดขึ้นของฟอร์แมตไฟล์ใหม่และข้อจำกัดของมัน
- เพื่อก้าวข้ามปัญหาเหล่านี้ จึงมีข้อเสนอฟอร์แมตไฟล์ใหม่ทั้งหมด เช่น Meta Nimble, Lance, TSFile, Bullion, BtrBlocks
- แต่ฟอร์แมตเหล่านี้ก็ยังทำ ความผิดพลาดแบบเดียวกัน กับรุ่นก่อนหน้า
- ออกแบบโดยอิงจากสมมติฐานฮาร์ดแวร์และเวิร์กโหลดของยุคปัจจุบัน
- ยังไม่เอื้อต่อ การขยายได้ง่าย ที่ทำให้รองรับฟีเจอร์ใหม่โดยไม่ทำลายการทำงานร่วมกับระบบที่ถูกติดตั้งใช้งานอยู่เดิม
- แม้หนึ่งในนั้นจะกลายเป็นฟอร์แมตหลักที่มาแทน Parquet หรือ ORC ผ่านไปอีก 10 ปีก็ยังจะเกิดปัญหาเดิมที่ต้องสร้างฟอร์แมตใหม่อีกเพื่อแก้ข้อบกพร่องของมัน
แนวทางของ F3
- F3 ตั้งเป้าหมายให้บรรลุทั้ง การทำงานร่วมกันได้ ความสามารถในการขยาย และประสิทธิภาพ ไปพร้อมกัน
- แกนหลักของ F3 คือการกำหนดสเปก 3 ส่วนดังนี้:
- เมทาดาทา ของเนื้อหาในไฟล์
- เลย์เอาต์การจัดกลุ่มทางกายภาพ ของข้อมูลที่ถูกเข้ารหัสภายในไฟล์
- Data Access API ที่ไม่ผูกกับสคีมการเข้ารหัสของข้อมูล
- สคีมเมทาดาทาของ F3 ลดข้อมูลที่จำเป็นสำหรับการดึงเฉพาะบางคอลัมน์ของตารางให้เหลือน้อยที่สุด
- F3 ตัดแนวคิด row group แบบครอบคลุมของ Parquet ออกไป และแก้ปัญหาเลย์เอาต์ด้วยการ แยกหน่วย I/O หน่วยการเข้ารหัส และหน่วยพจนานุกรม
- ผสานวิธีสมัยใหม่อย่าง staircase compression และ vectorized decoding
ภาพรวมของ F3
โครงสร้างโดยรวม
- ไฟล์ F3 ประกอบด้วย ส่วนเมทาดาทา และ ส่วนข้อมูล
- ส่วนเมทาดาทา: OptionalData(OptData), Column Metadata(ColMetadata), Footer, Postscript
- ส่วนข้อมูล: ประกอบด้วย Row Groups(RG) และบรรจุข้อมูลจริง
- F3 ใช้ เลย์เอาต์ PAX เช่นเดียวกับ Parquet และ ORC
- อย่างไรก็ตาม F3 มีความแตกต่างสำคัญจากฟอร์แมตเดิมหลายประการ:
- เมทาดาทาช่วย ขจัดโอเวอร์เฮดจากการ deserialize (แก้ปัญหาของ Parquet/ORC)
- แยก Physical I/O Unit(IOUnit) ออกจาก logical row group ทำให้ปรับขนาด IOUnit ได้อย่างอิสระตามสื่อจัดเก็บข้อมูล
- แยก ขอบเขตของ dictionary encoding ออกจาก logical row group เพื่อกำหนดขอบเขตที่มีประสิทธิภาพที่สุดได้ในแต่ละคอลัมน์
- แต่ละ IOUnit ประกอบด้วย Encoding Unit(EncUnit) หลายตัว โดย EncUnit เป็นหน่วยขั้นต่ำของการเข้ารหัสและถอดรหัส
กลไกด้านการทำงานร่วมกันและการขยาย
- F3 เปิดเผย API สาธารณะ เพื่อกำหนดวิธีที่ implementation จะใช้ถอดรหัสข้อมูลที่ถูกบีบอัดอยู่ในไฟล์
- มองวิธีการเข้ารหัสเป็น ปลั๊กอิน ที่สามารถติดตั้งและอัปเกรดแยกจากไลบรารีหลักได้
- เพื่อให้ไลบรารีทุกเวอร์ชันสามารถอ่านไฟล์ทุกไฟล์ได้ จึง ฝัง implementation ของตัวถอดรหัสเป็นไบนารี WebAssembly(Wasm) ไว้ภายในไฟล์
- กล่าวคือ ทุกไฟล์ F3 จะมีทั้งข้อมูลและโค้ดสำหรับอ่านข้อมูลนั้นรวมอยู่ด้วย
- API ของ F3 ไม่จำเป็นต้องมี implementation แยกสำหรับโค้ดแบบเนทีฟและเวอร์ชัน Wasm โดยสามารถคอมไพล์โค้ดเดียวกันไปยังทั้งสองเป้าหมายได้โดยไม่ต้องแก้ไข
- การออกแบบนี้ทำให้ F3 พร้อมรับอนาคต หลีกเลี่ยงปัญหาที่กล่าวมาก่อนหน้า และพัฒนาได้รวดเร็วกว่าวิธีเดิม
- นักพัฒนาสามารถฝังโค้ด Wasm ลงในไฟล์เพื่อปล่อยวิธีการเข้ารหัสแห่งอนาคตสู่ระบบ production ได้ โดยไม่ต้องกังวลเรื่องการอัปเกรดเวอร์ชันไลบรารีทั้งฟลีต
- สตอเรจโอเวอร์เฮดของไบนารี Wasm มีน้อยมาก (ระดับกิโลไบต์) และประสิทธิภาพที่ลดลงของการถอดรหัสด้วย Wasm เมื่อเทียบกับ implementation แบบเนทีฟก็ต่ำ (10~30%)
บทสรุป
- F3 คือฟอร์แมตไฟล์แบบคอลัมน์ยุคถัดไปที่บรรลุทั้ง การทำงานร่วมกันได้ ความสามารถในการขยาย และประสิทธิภาพ พร้อมกัน
- การออกแบบเลย์เอาต์ไฟล์ที่มีประสิทธิภาพช่วยแก้ความไม่มีประสิทธิภาพของฟอร์แมตเดิม
- Decoding API แบบปลั๊กอิน และ การฝัง Wasm มอบกลไกที่พร้อมรับอนาคต ทำให้สามารถอ่านไฟล์ทุกไฟล์ได้โดยไม่ขึ้นกับเวอร์ชันของไลบรารี
- ผลการประเมินต้นแบบพิสูจน์ประสิทธิภาพของการออกแบบเลย์เอาต์และความใช้งานได้จริงของกลไก Wasm
- โอเวอร์เฮดของ Wasm อยู่ในขอบเขตที่ยอมรับได้ คือใช้สตอเรจระดับกิโลไบต์และมีประสิทธิภาพลดลง 10~30%
1 ความคิดเห็น
ความเห็นบน Hacker News
จากที่ลองดูผ่าน ๆ รู้สึกว่ามันแก้จุดอ่อนของ Parquet ไปได้เยอะมาก เลยค่อนข้างคาดหวัง
เมทาดาทาของ Parquet แม้จะอิงกับ Thrift แต่ก็มีแค่คอมเมนต์แนว ๆ ว่า "ถ้ามีฟิลด์นี้ ก็ต้องมีอีกฟิลด์นั้นด้วย" โดยไม่มีตรรกะตรวจสอบจริง เลยคิดว่าถ้าใส่ Thrift ที่ผิดเข้าไป ตัว reader น่าจะพัง
เมทาดาทาของ Parquet ต้องถูก parse ก่อน ทำให้เกิดการจองบัฟเฟอร์และ dynamic allocation เพื่อ parse เมทาดาทาซ้ำ ๆ จนมี heap allocation มากเกินไป ฟอร์แมตนี้เลือกใช้แนวทางของ Flatbuffers จึงตีความไบต์ของ Flatbuffer ได้ตรง ๆ และแก้ปัญหานี้ได้
รู้สึกว่าการเข้ารหัสข้อมูลทรงพลังกว่ามาก น่าจะทำให้เกิด encoding แบบเบาและนำมาประกอบกันได้ตามที่วงการฐานข้อมูลผลักดันกันมานาน ฟอร์แมตเดิมอย่าง BtrBlocks และ FastLanes ก็เหนือกว่า Parquet อยู่แล้ว จึงดีที่ไอเดียดี ๆ ของพวกนั้นถูกสืบต่อมา
ส่วนตัวไม่ชอบ Dremel record-shredding ของ Parquet เพราะซับซ้อนเกินไป รอบนี้หายไปแล้วถือว่าเป็นข่าวดี
ใน Parquet จำนวน row ในแต่ละ DataPage ไม่เท่ากัน ถ้าจะหา row ที่ต้องการต้องสแกนทั้ง ColumnChunk แต่ฟอร์แมตนี้กระโดดไปยัง DataPage(IOUnit) ที่ต้องการได้ตรง ๆ
ตัด compression แบบหนักออก เหลือแค่ Delta/Dictionary/RLE เท่านั้น compression หนัก ๆ แทบไม่ได้ประโยชน์จริง แถมยุ่งยากต่อการ implement และมี external dependency เยอะ
โดยรวมถือว่าเป็นพัฒนาการที่ยอดเยี่ยม หวังว่าฟอร์แมตนี้จะครองวงการ data analytics ได้
ถ้า compression หนักที่ว่าคือ zstd หรือ brotli มันมีประโยชน์มากกับคอลัมน์สตริงที่มีการซ้ำน้อย
ถ้าใส่ wasm compiler เข้าไป อาจยิ่งเพิ่ม dependency มากกว่า compression แบบ ‘heavy’ เสียอีก
กระทู้ StackOverflow เรื่องการเพิ่มคอลัมน์ในไฟล์ Parquet
ทุกวันนี้ดูเหมือนวิธีบีบอัดจะลงตัวที่ zstd แล้วหรือเปล่า?
Parquet ซับซ้อนกว่าที่คิดมาก ถ้าจะใช้อย่างมีประสิทธิภาพจริง ๆ ต้องรู้รายละเอียดจุกจิกที่ทั้งใช้งานยากและเอกสารไม่ค่อยพอ จึงไม่ง่ายเลย
Wes McKinney
เผื่อใครไม่รู้จัก Wes McKinney เขาคือผู้สร้าง Pandas ไลบรารีวิเคราะห์ข้อมูลแบบตารางที่ถูกใช้งานมากที่สุดตัวหนึ่งใน Python
ฟอร์แมตที่เขาทำจึงมีโอกาสได้รับความเชื่อถือจากตลาดตั้งแต่ช่วงแรก และเพราะเขาสนใจปัญหานี้มาอย่างยาวนาน มุมมองของเขาจึงสำคัญเป็นพิเศษ
Andy Pavlo ก็เป็นคนที่ควรกล่าวถึงมาก
ในฐานะแฟนก็เห็นด้วยกับอิทธิพลของ Pandas แต่ในเชิงเทคนิคผมคิดว่าฟอร์แมตข้อมูล Arrow ส่งผลต่อ ecosystem ข้อมูลโดยรวมมากกว่าเสียอีก (เช่น DataFusion)
Wes McKinney ยังเป็นผู้สร้าง Apache Arrow ด้วย
ผมกลับรู้สึกว่างานของเขาที่ทำกับ Parquet ทำให้น่าเชื่อถือยิ่งขึ้นด้วยซ้ำ
การเอาข้อมูลกับโค้ดมาปะปนกันเป็นความผิดพลาดด้านความปลอดภัยแบบคลาสสิก
ดูเหมือนจะไม่ได้นำไปใช้กับอนาคตของนักฟิสิกส์
ข้อมูลระดับ exabyte ที่ผลิตจาก CERN Large Hadron Collider ในอีก 20 ปีข้างหน้าจะยังใช้ฟอร์แมตที่ CERN พัฒนาขึ้นเอง
เอกสารเกี่ยวกับฟอร์แมตข้อมูลของ CERN
CERN อยู่กับข้อมูลขนาดใหญ่มาตั้งแต่ก่อนคนส่วนใหญ่ในวงการนี้มาก
อยากขออภัยที่ยังไม่ค่อยเข้าใจความแตกต่างจากการจัดเก็บแบบ column-oriented มากนัก
เลยสงสัยว่าทำไมสิ่งนี้ถึงถือว่าเป็นนวัตกรรม หรือแก่นจริง ๆ คือ "การส่งฐานข้อมูล vector embedding ขนาดเล็กพร้อม sandbox" ใช่ไหม
จากงานวิจัยให้ความรู้สึกเหมือนเป็นรากฐานใหม่ได้ และชื่อโปรเจกต์ก็ให้อารมณ์แบบฝรั่งเศสอยู่เหมือนกัน(?)
ผมเองเข้าใจเนื้อหาไม่มากนัก แต่รู้สึกว่าภาพกับโทนสีสวยและกล้าดี ในฐานะคนที่โดนโน้มน้าวได้ง่ายก็ขอยกสองนิ้วให้
แก่นสำคัญคือ compatibility layer
จุดเด่นจริง ๆ ของการเก็บแบบคอลัมน์คือสามารถแตก nested schema ที่ซับซ้อนออกเป็นค่า primitive แล้วเก็บได้
ประโยชน์แท้จริงของการเก็บแบบคอลัมน์คือการสแกนทั้ง column ได้เร็วมากในคราวเดียว
ค่อนข้างเสียดายที่ wasm decoder ช้ากว่า native 10-30%
เท่ากับยอมรับ performance loss 10-30% ตั้งแต่ต้น และเหมือนยอมสละโอกาสในการปรับปรุง decoder ต่อไปแบบถาวร
ฟีเจอร์การ decode ขั้นสูงที่นอกเหนือจาก "decode ทั้งบล็อกแล้วเก็บลงหน่วยความจำ" ก็ใช้ไม่ได้ด้วย
ไม่เข้าใจจริง ๆ ว่าทำไมต้องออกแบบแบบนี้
ถ้าความเร็วสำคัญ wasm ก็ไม่ใช่คำตอบ และถ้าความเร็วไม่สำคัญ ก็น่าจะใช้ encoding มาตรฐานที่รู้จักกันดีไปเลย
WASM ถูกเตรียมไว้เป็นทางเลือกสำรอง
เห็นด้วยบางส่วน แต่เรื่องนี้ซับซ้อนกว่านั้นอีก
ยังไม่เข้าใจความสัมพันธ์ระหว่าง Vortex กับ F3 ชัดเจน
ทั้งคู่พูดถึงวิสัยทัศน์ว่า "ออกแบบให้เพิ่มวิธี encoding ได้ง่าย โดยไม่ต้องสร้างฟอร์แมตใหม่"
ในบทแนะนำบอกว่าใช้ implementation ของ encoding จาก Vortex แต่ก็เขียนไว้ว่าระบบชนิดข้อมูลต่างกัน
ภูมิหลังของการเดินโปรเจกต์ค่อนข้างซับซ้อน
ฟังแล้วเริ่มรอ F4 ของปีหน้าเลย
ผมหา source code อยู่นาน สุดท้ายเจอว่า เปิดอยู่ที่นี่
การจะอ่านข้อมูลได้ต้องมีข้อผูกมัดว่าต้องรัน webassembly เสมอ เลยคิดว่าไม่เหมาะกับสภาพแวดล้อมที่อยากลด dependency หรือ bloat
wasm นั้นเรียบง่าย
ถ้ามี native decoder ก็ไม่จำเป็นต้องใช้ WASM
ดูเหมือนจะเป็นหนึ่งในฟอร์แมตไฟล์แรก ๆ ที่ฝังโมดูล WebAssembly ลงไป
ผมสนใจมากโดยเฉพาะในมุมของ compression เพราะถ้าออกแบบ WASM preprocessor ดี ๆ อาจเพิ่มอัตราการบีบอัดได้มาก
ผมเองก็กำลังทำฟอร์แมตไฟล์ตามคอนเซปต์นี้อยู่เหมือนกัน
Alan Kay เคยอธิบายระบบจัดเก็บข้อมูลบนเทปที่น่าจะมีโปรแกรมเมอร์คนหนึ่งทำไว้ตั้งแต่ยุค 60 ว่าเป็น ‘ระบบเชิงวัตถุระบบแรก’