นี่เป็นการใช้งานเครื่องอ่าน/เขียนรูปแบบไฟล์ไม้ปาร์เก้ครั้งแรกใน PHP โดยอิงจากแหล่งข้อมูล Thrift ที่จัดทำโดย Apache Foundation โค้ดและแนวคิดส่วนใหญ่ได้รับการย้ายจาก parquet-dotnet (ดู https://github.com/elastacloud/parquet-dotnet และ https://github.com/aloneguid/parquet-dotnet) ดังนั้นขอขอบคุณ Ivan Gavryliuk (https://github.com/aloneguid)
แพ็คเกจนี้ช่วยให้คุณสามารถอ่านและเขียนไฟล์/สตรีม Parquet โดยไม่ต้องใช้ส่วนขยายภายนอกที่แปลกใหม่ (ยกเว้นคุณต้องการใช้วิธีการบีบอัดที่แปลกใหม่) มีการทดสอบความเข้ากันได้ (เกือบ) 100% กับ parquet-dotnet เกี่ยวกับฟังก์ชันหลักที่ทำผ่าน PHPUnit
พื้นที่เก็บข้อมูลนี้ (และแพ็คเกจที่เกี่ยวข้องกับ Packagist) เป็นโครงการต่อเนื่องอย่างเป็นทางการของ jocoon/parquet
เนื่องจากการปรับปรุงต่างๆ และการแก้ไขข้อบกพร่องที่สำคัญ ใน codename/parquet
การใช้แพ็คเกจแบบเดิมจึงไม่สนับสนุนอย่างยิ่ง
สำหรับบางส่วนของแพ็คเกจนี้ จำเป็นต้องคิดค้นรูปแบบใหม่บางอย่าง เนื่องจากฉันไม่พบการใช้งานที่ตรงตามข้อกำหนด ในกรณีส่วนใหญ่ ไม่มีการใช้งานใดๆ เลย
ไฮไลท์บางส่วน:
ฉันเริ่มพัฒนาไลบรารีนี้เนื่องจากไม่มีการใช้งาน PHP
ที่บริษัทของฉัน เราต้องการโซลูชันที่รวดเร็วในการจัดเก็บข้อมูลจำนวนมหาศาลจากฐานข้อมูลในรูปแบบที่ยังสามารถสืบค้นได้ ขยายได้จากมุมมองของสคีมา และทนทานต่อข้อผิดพลาด เราเริ่มทดสอบ 'การย้าย' แบบเรียลไทม์ผ่าน AWS DMS ไปยัง S3 ซึ่งจบลงด้วยการหยุดทำงานของข้อมูลจำนวนหนึ่ง เนื่องจากข้อจำกัดของหน่วยความจำ และมันก็เน้นที่ db มากเกินไป อีกอย่างคือมันง่ายที่จะลบข้อมูลออกจากการโหลดครั้งก่อนโดยไม่ตั้งใจ เนื่องจากเรามีสถาปัตยกรรมที่เน้น SDS และไม่เชื่อเรื่องพระเจ้าบนแพลตฟอร์ม จึงไม่ใช่วิธีที่ฉันชอบในการจัดเก็บข้อมูลในรูปแบบโคลนฐานข้อมูล 1:1 เช่นดัมพ์ แต่ฉันต้องการให้มีความสามารถในการจัดเก็บข้อมูลที่มีโครงสร้างแบบไดนามิกตามที่ฉันต้องการ ในลักษณะเดียวกับที่ DMS ส่งออกไปยัง S3 ในที่สุดโครงการก็เสียชีวิตเนื่องจากเหตุผลที่กล่าวมาข้างต้น
แต่ฉันเอารูปแบบไม้ปาร์เก้ออกจากหัวไม่ได้..
ผลการค้นหา 1 อันดับแรก (https://stackoverflow.com/questions/44780419/how-to-create-orc-or-parquet-files-from-php-code) ดูมีแนวโน้มว่าจะไม่ต้องใช้ความพยายามมากขนาดนั้น การใช้งาน PHP - แต่จริงๆ แล้วต้องใช้เวลาพอสมควร (งานไม่ติดต่อกันประมาณ 2 สัปดาห์) สำหรับฉัน ในฐานะนักพัฒนา PHP และ C# parquet-dotnet เป็นจุดเริ่มต้นที่สมบูรณ์แบบ ไม่ใช่แค่เพราะว่าการวัดประสิทธิภาพนั้นน่าดึงดูดเกินไปเท่านั้น แต่ฉันคาดว่าการใช้งาน PHP จะไม่เป็นไปตามระดับประสิทธิภาพเหล่านี้ เนื่องจากนี่เป็นการใช้งานครั้งแรกซึ่งแสดงให้เห็นหลักการ และอีกอย่างไม่มีใครเคยทำมาก่อน
เนื่องจาก PHP มีส่วนแบ่งจำนวนมากเกี่ยวกับโครงการที่เกี่ยวข้องกับเว็บ นี่จึงเป็นสิ่ง ที่ต้องมี ในช่วงเวลาที่มีความต้องการแอปพลิเคชันและสถานการณ์ Big Data เพิ่มขึ้น สำหรับแรงจูงใจส่วนตัวของฉัน นี่เป็นวิธีที่จะแสดงให้เห็นว่า PHP (ในเชิงกายภาพหรือเสมือนจริง) เหนือกว่าชื่อเสียงในฐานะ 'ภาษาสคริปต์' ฉันคิดว่า - หรืออย่างน้อยฉันก็หวังว่า - มีผู้คนจำนวนมากที่จะได้รับประโยชน์จากแพ็คเกจนี้และข้อความที่ส่งผ่าน ไม่เพียงแต่วัตถุดริฟท์เท่านั้น ปุณตั้งใจ.
คุณจะต้องมีส่วนขยายหลายรายการเพื่อใช้ไลบรารีนี้อย่างเต็มประสิทธิภาพ
ไลบรารีนี้เดิมได้รับการพัฒนาเป็น/ใช้ PHP 7.3 แต่ควรใช้งานได้กับ PHP > 7 และจะทดสอบในวันที่ 8 เมื่อเผยแพร่ ในขณะนี้ การทดสอบ PHP 7.1 และ 7.2 จะล้มเหลวเนื่องจากปัญหา DateTime บางประการ ฉันจะได้ดูมัน. การทดสอบผ่าน PHP 7.3 และ 7.4 อย่างสมบูรณ์ ในขณะที่เขียนนี้ 8.0.0 RC2 ก็ทำงานได้ดีเช่นกัน
ห้องสมุดนี้ขึ้นอยู่กับอย่างมาก
ตั้งแต่เวอร์ชัน 0.2 ฉันได้เปลี่ยนไปใช้แนวทางการใช้งานแบบไม่เชื่อเรื่องพระเจ้าในการใช้ตัวอ่านและผู้เขียน ตอนนี้ เรากำลังจัดการกับการใช้งาน BinaryReader(Interface) และ BinaryWriter(Interface) ที่เป็นนามธรรมของกลไกพื้นฐาน ฉันสังเกตเห็นว่า mdurrant/php-binary-reader ช้าเกินไป ฉันไม่ต้องการปรับโครงสร้างใหม่ทุกอย่างเพียงเพื่อลองใช้พลังการอ่านของ Nelexa แต่ฉันได้สร้างอินเทอร์เฟซทั้งสองที่กล่าวถึงข้างต้นให้เป็นแพ็คเกจต่าง ๆ ที่เป็นนามธรรมซึ่งนำเสนอการอ่าน/การเขียนแบบไบนารี ในที่สุดสิ่งนี้นำไปสู่วิธีที่ดีที่สุดในการทดสอบ/เปรียบเทียบการใช้งานที่แตกต่างกัน - และยังผสมผสาน เช่น การใช้แพ็คเกจของ wapmorgan สำหรับการอ่าน ในขณะที่ใช้ Nelexa's ในการเขียน
ตั้งแต่เวอร์ชัน 0.2.1 ฉันได้ดำเนินการใช้งานโปรแกรมอ่าน/เขียนไบนารีด้วยตนเองแล้ว เนื่องจากไม่มีการใช้งานใดที่ตรงตามข้อกำหนดด้านประสิทธิภาพ โดยเฉพาะอย่างยิ่งสำหรับการเขียน การใช้งานที่มีน้ำหนักเบาเป็นพิเศษนี้ให้ประสิทธิภาพของบัฟเฟอร์ของ Nelexa ถึงสาม*
*ตั้งใจว่าชอบคำนี้
แพ็คเกจการอ่าน/เขียนไบนารีทางเลือกของบุคคลที่สามในขอบเขต:
ติดตั้งแพ็คเกจนี้ผ่านผู้แต่งเช่น
composer require codename/parquet
Dockerfile ที่ให้มาช่วยให้คุณทราบถึงความต้องการของระบบที่จำเป็น สิ่งที่สำคัญที่สุดที่ต้องทำคือการโคลนและติดตั้ง php-ext-snappy ในขณะที่เขียนยัง ไม่มีการเผยแพร่ PECL
...
# NOTE: this is a dockerfile snippet. Bare metal machines will be a little bit different
RUN git clone --recursive --depth=1 https://github.com/kjdev/php-ext-snappy.git
&& cd php-ext-snappy
&& phpize
&& ./configure
&& make
&& make install
&& docker-php-ext-enable snappy
&& ls -lna
...
โปรดทราบ: php-ext-snappy นั้นค่อนข้างแปลกเล็กน้อยในการคอมไพล์และติดตั้งบน Windows ดังนั้นนี่เป็นเพียงข้อมูลสั้นๆ สำหรับการติดตั้งและการใช้งานบนระบบที่ใช้ Linux ตราบใดที่คุณไม่จำเป็นต้องมีการบีบอัดที่รวดเร็วในการอ่านหรือเขียน คุณสามารถใช้ php-parquet ได้โดยไม่ต้องคอมไพล์ด้วยตัวเอง
ฉันพบ ParquetViewer (https://github.com/mukunku/ParquetViewer) โดย Mukunku เพื่อเป็นวิธีที่ดีในการดูข้อมูลที่จะอ่านหรือตรวจสอบบางสิ่งบนเครื่องเดสก์ท็อป Windows อย่างน้อยก็ช่วยให้เข้าใจกลไกบางอย่างได้ เนื่องจากจะช่วยแสดงข้อมูลเป็นตารางได้ไม่มากก็น้อย
การใช้งานเกือบจะเหมือนกับ parquet-dotnet โปรดทราบว่าเราไม่มี using ( ... ) { }
เหมือนใน C# ดังนั้นคุณต้องแน่ใจว่าได้ปิด/กำจัดทรัพยากรที่ไม่ได้ใช้ด้วยตัวเอง หรือปล่อยให้ GC ของ PHP จัดการโดยอัตโนมัติด้วยอัลกอริธึมการนับใหม่ (นี่คือเหตุผลที่ฉันไม่ใช้ destructors เหมือน parquet-dotnet ใช้)
เนื่องจากระบบประเภทของ PHP แตกต่างจาก C# อย่างสิ้นเชิง เราจึงต้องเพิ่มวิธีจัดการข้อมูลบางประเภท ตัวอย่างเช่น จำนวนเต็ม PHP นั้นเป็นโมฆะได้ แต่อย่างใด int ใน C # ไม่ใช่ นี่เป็นประเด็นที่ฉันยังไม่แน่ใจว่าจะจัดการกับมันอย่างไร สำหรับตอนนี้ฉันได้ตั้งค่า int (PHP integer ) ให้เป็นโมฆะ - parquet-dotnet กำลังทำสิ่งนี้ว่าไม่เป็นโมฆะ คุณสามารถปรับพฤติกรรมนี้ได้ตลอดเวลาโดยการตั้งค่าด้วยตนเอง ->hasNulls = true;
บน DataField ของคุณ นอกจากนี้ php-parquet ยังใช้วิธีสองทางในการกำหนดประเภท ใน PHP นั้น primitive จะมีประเภทเป็นของตัวเอง (จำนวนเต็ม, bool, float/double ฯลฯ) สำหรับอินสแตนซ์คลาส (โดยเฉพาะ DateTime/DateTimeImmutable) ประเภทที่ส่งคืนโดย get_type() จะเป็นอ็อบเจ็กต์เสมอ นี่คือเหตุผลที่คุณสมบัติที่สองสำหรับ DataTypeHandlers มีอยู่เพื่อจับคู่ กำหนด และประมวลผล: phpClass
ในขณะที่เขียนนี้ ไม่ใช่ทุก DataType ที่รองรับ parquet-dotnet จะได้รับการสนับสนุนที่นี่เช่นกัน Fe ฉันได้ข้าม Int16, SignedByte และอื่นๆ ไปแล้ว แต่ก็ไม่ควรซับซ้อนเกินไปที่จะขยายไปสู่ความเข้ากันได้แบบไบนารีเต็มรูปแบบ
ในขณะนี้ ไลบรารีนี้ให้บริการฟังก์ชัน หลัก ที่จำเป็นสำหรับการอ่านและเขียนไฟล์/สตรีมไม้ปาร์เก้ ไม่รวม Table, Row, Enumerators/helpers ของ parquet-dotnet จากเนมสเปซ C# Parquet.Data.Rows
use codename parquet ParquetReader ;
// open file stream (in this example for reading only)
$ fileStream = fopen ( __DIR__ . ' /test.parquet ' , ' r ' );
// open parquet file reader
$ parquetReader = new ParquetReader ( $ fileStream );
// Print custom metadata or do other stuff with it
print_r ( $ parquetReader -> getCustomMetadata ());
// get file schema (available straight after opening parquet reader)
// however, get only data fields as only they contain data values
$ dataFields = $ parquetReader -> schema -> GetDataFields ();
// enumerate through row groups in this file
for ( $ i = 0 ; $ i < $ parquetReader -> getRowGroupCount (); $ i ++)
{
// create row group reader
$ groupReader = $ parquetReader -> OpenRowGroupReader ( $ i );
// read all columns inside each row group (you have an option to read only
// required columns if you need to.
$ columns = [];
foreach ( $ dataFields as $ field ) {
$ columns [] = $ groupReader -> ReadColumn ( $ field );
}
// get first column, for instance
$ firstColumn = $ columns [ 0 ];
// $data member, accessible through ->getData() contains an array of column data
$ data = $ firstColumn -> getData ();
// Print data or do other stuff with it
print_r ( $ data );
}
use codename parquet ParquetWriter ;
use codename parquet data Schema ;
use codename parquet data DataField ;
use codename parquet data DataColumn ;
//create data columns with schema metadata and the data you need
$ idColumn = new DataColumn (
DataField:: createFromType ( ' id ' , ' integer ' ), // NOTE: this is a little bit different to C# due to the type system of PHP
[ 1 , 2 ]
);
$ cityColumn = new DataColumn (
DataField:: createFromType ( ' city ' , ' string ' ),
[ " London " , " Derby " ]
);
// create file schema
$ schema = new Schema ([ $ idColumn -> getField (), $ cityColumn -> getField ()]);
// create file handle with w+ flag, to create a new file - if it doesn't exist yet - or truncate, if it exists
$ fileStream = fopen ( __DIR__ . ' /test.parquet ' , ' w+ ' );
$ parquetWriter = new ParquetWriter ( $ schema , $ fileStream );
// optional, write custom metadata
$ metadata = [ ' author ' => ' santa ' , ' date ' => ' 2020-01-01 ' ];
$ parquetWriter -> setCustomMetadata ( $ metadata );
// create a new row group in the file
$ groupWriter = $ parquetWriter -> CreateRowGroup ();
$ groupWriter -> WriteColumn ( $ idColumn );
$ groupWriter -> WriteColumn ( $ cityColumn );
// As we have no 'using' in PHP, I implemented finish() methods
// for ParquetWriter and ParquetRowGroupWriter
$ groupWriter -> finish (); // finish inner writer(s)
$ parquetWriter -> finish (); // finish the parquet writer last
คุณยังสามารถใช้ ParquetDataIterator
และ ParquetDataWriter
เพื่อทำงานแม้จะมีสคีมาที่ซับซ้อนสูง (fe ที่ซ้อนกัน) แม้ว่าจะเป็นการทดลองในขณะที่เขียน การทดสอบหน่วยและการรวมระบบระบุว่าเรามีความเข้ากันได้ 100% กับ Spark เนื่องจากการใช้งาน Parquet อื่นๆ ส่วนใหญ่ขาดคุณสมบัติบางอย่างหรือกรณีของการซ้อนที่ซับซ้อนเป็นพิเศษ
ParquetDataIterator
และ ParquetDataWriter
ใช้ประโยชน์จาก 'ความเป็นไดนามิก' ของระบบประเภท PHP และอาร์เรย์ (แบบเชื่อมโยง) ซึ่งจะหยุดชะงักเมื่อใช้จำนวนเต็ม 64 บิตที่ไม่ได้ลงนามอย่างเต็มที่ ซึ่งสามารถรองรับได้เพียงบางส่วนเท่านั้นเนื่องจากลักษณะของ PHP
ParquetDataIterator
จะวนซ้ำกลุ่มแถวและหน้าข้อมูลทั้งหมดโดยอัตโนมัติ ในทุกคอลัมน์ของไฟล์ parquet ด้วยวิธีที่มีประสิทธิภาพหน่วยความจำมากที่สุดเท่าที่จะเป็นไปได้ ซึ่งหมายความว่า มันไม่ได้โหลดชุดข้อมูลทั้งหมดลงในหน่วยความจำ แต่จะโหลดแบบต่อหน้า/ต่อแถว-กลุ่ม
ภายใต้ประทุนนั้นใช้ประโยชน์จากฟังก์ชันการทำงานของ DataColumnsToArrayConverter
ซึ่งท้ายที่สุดจะ 'ยกของหนัก' ทั้งหมดเกี่ยวกับ คำจำกัดความและระดับการทำซ้ำ
use codename parquet helper ParquetDataIterator ;
$ iterateMe = ParquetDataIterator:: fromFile ( ' your-parquet-file.parquet ' );
foreach ( $ iterateMe as $ dataset ) {
// $dataset is an associative array
// and already combines data of all columns
// back to a row-like structure
}
ในทางกลับกัน ParquetDataWriter
ช่วยให้คุณสามารถเขียนไฟล์ Parquet ได้ 2 ไฟล์ (ในหน่วยความจำหรือบนดิสก์) โดยการส่งข้อมูลอาเรย์เชื่อมโยง PHP ทีละรายการหรือเป็นชุด ภายในจะใช้ ArrayToDataColumnsConverter
เพื่อสร้างข้อมูล พจนานุกรม คำจำกัดความ และระดับการทำซ้ำ
use codename parquet helper ParquetDataWriter ;
$ schema = new Schema ([
DataField:: createFromType ( ' id ' , ' integer ' ),
DataField:: createFromType ( ' name ' , ' string ' ),
]);
$ handle = fopen ( ' sample.parquet ' , ' r+ ' );
$ dataWriter = new ParquetDataWriter ( $ handle , $ schema );
// add two records at once
$ dataToWrite = [
[ ' id ' => 1 , ' name ' => ' abc ' ],
[ ' id ' => 2 , ' name ' => ' def ' ],
];
$ dataWriter -> putBatch ( $ dataToWrite );
// we add a third, single one
$ dataWriter -> put ([ ' id ' => 3 , ' name ' => ' ghi ' ]);
$ dataWriter -> finish (); // Don't forget to finish at some point.
fclose ( $ handle ); // You may close the handle, if you have to.
php-parquet รองรับความสามารถในการซ้อนเต็มรูปแบบของรูปแบบ Parquet คุณอาจสังเกตเห็นว่าคุณกำลัง 'สูญเสีย' ชื่อคีย์ ขึ้นอยู่กับประเภทฟิลด์ที่คุณซ้อนอยู่ นี่คือโดยการออกแบบ:
โดยทั่วไปแล้ว นี่คือ PHP ที่เทียบเท่ากับประเภทลอจิคัลของรูปแบบ Parquet:
ปาร์เก้ | PHP | เจสัน | บันทึก |
---|---|---|---|
DataField | ดั้งเดิม | ดั้งเดิม | สตริง fe, จำนวนเต็ม ฯลฯ |
รายการฟิลด์ | อาร์เรย์ | อาร์เรย์ [] | ประเภทองค์ประกอบอาจเป็นรายการ โครงสร้าง หรือแผนที่ก็ได้ |
โครงสร้างField | อาร์เรย์ที่เชื่อมโยง | วัตถุ {} | กุญแจของรศ. อาร์เรย์คือชื่อฟิลด์ภายใน StructField |
MapField | อาร์เรย์ที่เชื่อมโยง | วัตถุ {} | แบบง่าย: array_keys($data['someField']) และ array_values($data['someField']) แต่สำหรับแต่ละแถว |
รูปแบบนี้เข้ากันได้กับข้อมูลการส่งออก JSON ที่สร้างโดย Spark ที่กำหนดค่าด้วย spark.conf.set("spark.sql.jsonGenerator.ignoreNullFields", False)
ตามค่าเริ่มต้น Spark จะตัดค่า null
ออกทั้งหมดเมื่อส่งออกไปยัง JSON
โปรดทราบ: ประเภทฟิลด์ทั้งหมดเหล่านี้ สามารถ ทำให้เป็นโมฆะหรือไม่เป็นโมฆะได้/จำเป็นในทุกระดับการซ้อน (ส่งผลต่อระดับคำจำกัดความ) ความเป็นโมฆะบางอย่างถูกใช้ fe เพื่อแสดงรายการว่างและแยกความแตกต่างจากค่า null
สำหรับรายการ
use codename parquet helper ParquetDataIterator ;
use codename parquet helper ParquetDataWriter ;
$ schema = new Schema ([
DataField:: createFromType ( ' id ' , ' integer ' ),
new MapField (
' aMapField ' ,
DataField:: createFromType ( ' someKey ' , ' string ' ),
StructField:: createWithFieldArray (
' aStructField '
[
DataField:: createFromType ( ' anInteger ' , ' integer ' ),
DataField:: createFromType ( ' aString ' , ' string ' ),
]
)
),
StructField:: createWithFieldArray (
' rootLevelStructField '
[
DataField:: createFromType ( ' anotherInteger ' , ' integer ' ),
DataField:: createFromType ( ' anotherString ' , ' string ' ),
]
),
new ListField (
' aListField ' ,
DataField:: createFromType ( ' someInteger ' , ' integer ' ),
)
]);
$ handle = fopen ( ' complex.parquet ' , ' r+ ' );
$ dataWriter = new ParquetDataWriter ( $ handle , $ schema );
$ dataToWrite = [
// This is a single dataset:
[
' id ' => 1 ,
' aMapField ' => [
' key1 ' => [ ' anInteger ' => 123 , ' aString ' => ' abc ' ],
' key2 ' => [ ' anInteger ' => 456 , ' aString ' => ' def ' ],
],
' rootLevelStructField ' => [
' anotherInteger ' => 7 ,
' anotherString ' => ' in paradise '
],
' aListField ' => [ 1 , 2 , 3 ]
],
// ... add more datasets as you wish.
];
$ dataWriter -> putBatch ( $ dataToWrite );
$ dataWriter -> finish ();
$ iterateMe = ParquetDataIterator:: fromFile ( ' complex.parquet ' );
// f.e. write back into a full-blown php array:
$ readData = [];
foreach ( $ iterateMe as $ dataset ) {
$ readData [] = $ dataset ;
}
// and now compare this to the original data supplied.
// manually, by print_r, var_dump, assertions, comparisons or whatever you like.
แพคเกจนี้ยังให้เกณฑ์มาตรฐานเดียวกันกับ parquet-dotnet นี่คือผลลัพธ์บน เครื่องของฉัน :
Parquet.Net (.NET Core 2.1) | php-parquet (โลหะเปลือย 7.3) | php-ปาร์เก้ (เทียบท่า * 7.3) | Fastparquet (หลาม) | ปาร์เก้นาย (ชวา) | |
---|---|---|---|---|---|
อ่าน | 255ms | 1'090มิลลิวินาที | 1'244มิลลิวินาที | 154ms** | ยังไม่ทดลอง |
เขียน (ไม่บีบอัด) | 209ms | 1'272ms | 1'392ms | 237ms** | ยังไม่ทดลอง |
เขียน (gzip) | 1'945มิลลิวินาที | 3'314มิลลิวินาที | 3'695ms | 1'737ms** | ยังไม่ทดลอง |
โดยทั่วไป การทดสอบเหล่านี้ดำเนินการด้วยการบีบอัด gzip ระดับ 6 สำหรับ php-parquet จะลดลงประมาณครึ่งหนึ่งด้วย 1 (การบีบอัดขั้นต่ำ) และเกือบสองเท่าที่ 9 (การบีบอัดสูงสุด) โปรดทราบว่าอย่างหลังอาจไม่ให้ขนาดไฟล์เล็กที่สุด แต่จะใช้เวลาในการบีบอัดนานที่สุดเสมอ
เนื่องจากนี่เป็นพอร์ตบางส่วนของแพ็คเกจจากภาษาการเขียนโปรแกรมที่แตกต่างไปจากเดิมอย่างสิ้นเชิง รูปแบบการเขียนโปรแกรมจึงค่อนข้างยุ่งเหยิงทีเดียว ฉันตัดสินใจที่จะเก็บเคสส่วนใหญ่ไว้ (เช่น $writer->CreateRowGroup() แทน ->createRowGroup()) เพื่อคง 'ความเข้ากันได้ทางภาพ' ไว้กับ parquet-dotnet อย่างน้อย นี่เป็นสถานะที่น่าพอใจจากมุมมองของฉัน เนื่องจากทำให้การเปรียบเทียบและขยายง่ายขึ้นมากในระหว่างขั้นตอนการพัฒนาเริ่มแรก
โค้ดบางส่วนและแนวคิดได้รับการย้ายจาก C#/.NET ดู:
php-parquet ได้รับอนุญาตภายใต้ใบอนุญาต MIT ดูไฟล์ใบอนุญาต
ถ้าต้องการก็ทำ PR ได้เลย เนื่องจากนี่เป็นโปรเจ็กต์ OSS เวลาว่าง การสนับสนุนจะช่วยเหลือผู้ใช้แพ็คเกจนี้ทุกคน รวมถึงตัวคุณเองด้วย โปรดใช้สามัญสำนึกเล็กน้อยในการสร้างประชาสัมพันธ์และ/หรือประเด็นต่างๆ เนื่องจากไม่มีเทมเพลต