— K’s Curious Lane: Where Curiosity Never Ends

Comparison of Query Performance Between CSV and Parquet Files

บทความนี้จะทำการเปรียบเทียบประสิทธิภาพการ Query ระหว่าง CSV และ Parquet File บน Hive + PySpark ก่อนอื่นมาทำความรู้จักกับเครื่องมือและ file format ที่จะถูกนำมาเปรียบเทียบกัน ดังนี้

Hadoop

คือเครื่องมือ open source ที่ใช้ในการเก็บข้อมูลและประมวลผลข้อมูลขนาดใหญ่ มีแนวคิดคือการนำคอมพิวเตอร์หลายๆ เครื่อง (node) มาเก็บข้อมูลและประมวลผลร่วมกันเพื่อเพิ่มประสิทธิภาพและรองรับข้อมูลปริมาณมาก โดยมีส่วนประกอบหลัก 3 ส่วนคือ HDFS (Hadoop Distributed File System) สำหรับจัดเก็บข้อมูลขนาดใหญ่แบบกระจาย Mapreduce สำหรับประมวลผลข้อมูลขนาดใหญ่แบบกระจายตัว และ Yarn (Yet Another Resource Negotiator) ทำหน้าที่เป็น resource management จัดสรรทรัพยากรข้อมูลภายใน cluster

โดยใน hadoop ยังมีเครื่องมือที่ใช้ทำงานร่วมกันอีกมากมาย อาทิ Hive (ใช้ sql เพื่อสืบค้นข้อมูลบน Hadoop) Pig (ใช้ภาษา script สำหรับประมวลผลและแปลงข้อมูล) Sqoop (ใช้สำหรับ: Import ข้อมูลเข้า Hadoop หรือ Export ข้อมูลออกไปยังฐานข้อมูล RDBMS อื่น เช่น MySQL, PostgreSQL) เป็นต้น

ขอบคุณภาพจาก : https://blog.datath.com/hadoop-hdfs-yarn-mapreduce/

HIVE

Hive คือระบบคลังข้อมูล (Data Warehouse) ที่สร้างอยู่บน Apache Hadoop ทำหน้าที่ส่วนกลางในการเก็บข้อมูลที่สามารถนำมาวิเคราะห์เพื่อทำการตัดสินใจได้ Hive มีจุดเด่นคือช่วยให้ผู้ใช้อ่าน เขียนข้อมูลได้ด้วยภาษา SQL


ดย File format ที่จะนำมาทำการเปรียบเทียบกันมีดังนี้

ขอบคุณภาพจาก : https://medium.com/@mhsilvav/why-apache-parquet-instead-of-csv-files-3d2a0cd7cbf6

CSV File

CSV ย่อมาจาก Comma-Separated Values เป็น text file ที่เก็บข้อมูลแบบตาราง โดยเป็นแบบ Row-based ซึ่งเหมาะกับการต้องอ่านและเขียนข้อมูลทั้งแถวบ่อยๆ ไฟล์ CSV สามารถเปิดได้ใน Excel, Google Sheets, Notepad หรือโปรแกรมวิเคราะห์ข้อมูลต่าง ๆ เช่น Python (pandas), R, SQL เป็นต้น สามารถเปิดใน Apache Hive ได้โดยใช้การเก็บข้อความแบบ TEXTFILE

ตัวอย่างไฟล์ CSV :

Name, Age, City  
Alice, 25, Bangkok  
Bob, 30, Chiang Mai  
Charlie, 22, Phuket

Parquet File

เป็นไฟล์ binary ที่จัดเก็บแบบ column-based โดยการจัดเก็บแบบ column-based ถือเป็นส่วนสำคัญที่ช่วยเพิ่มประสิทธิภาพการ query เนื่องจากช่วยลด disk I/O requirement เป็นอย่างมาก รวมถึงลดปริมาณข้อมูลที่โหลดจากดิสก์อีกด้วย

โดยความแตกต่างระหว่างการเก็บข้อมูลแบบ Row-based และ Column-Based มีดังนี้

การเก็บข้อมูลแบบ Row-based จะเก็บข้อมูลเป็นแถว (row) โดยแต่ละแถวจะมีข้อมูลของทุกคอลัมน์ที่เกี่ยวข้องอยู่ด้วยกัน เหมาะกับการดึงข้อมูลเป็นแถว (เช่น ดึงข้อมูลของผู้ใช้หนึ่งคนทั้งหมด) แต่ถ้าต้องการดึงข้อมูลเฉพาะบางคอลัมน์ เช่น อายุ (Age) ของทุกคน ระบบต้องอ่านทุกแถวแล้วดึงค่าของคอลัมน์นั้นออกมา ซึ่งอาจช้ากว่า Column-based Storage ที่จัดเก็บข้อมูลแบบแยกคอลัมน์ (Column-Oriented)

ตัวอย่างการเก็บข้อมูลแบบ Row-based ขอบคุณภาพจาก : https://docs.aws.amazon.com/redshift/latest/dg/c_columnar_storage_disk_mem_mgmnt.html

ตัวอย่างการเก็บข้อมูลแบบ Column-based ขอบคุณภาพจาก : https://docs.aws.amazon.com/redshift/latest/dg/c_columnar_storage_disk_mem_mgmnt.html

📂 Workflow

1. เตรียมข้อมูลและ set up environment

2. โหลดข้อมูล CSV ลง Hive ในรูปแบบ TEXTFILE และ Parquet

3. ตั้งค่า Zeppelin และรัน Query

4. วิเคราะห์ผลลัพธ์


1️⃣ เตรียมข้อมูลและ set up environment

ข้อมูลทดสอบที่นำมาใช้คือ Amazon Review ที่ตัดมาบางส่วน จำนวนประมาณ 55,000 แถว สามารถดาวน์โหลดข้อมูลเต็มได้ที่นี่

โดยในโปรเจ็กต์นี้จะทำการเปรียบเทียบความเร็วในการ Query ระหว่าง TEXTFILE (CSV file) และ Parquet file

  • เริ่มจากการสร้าง EMR Cluster ใน AWS ก่อน โดยให้ติ๊กเลือก tools ที่จะใช้ ในที่นี้คือดังรูปด้านล่าง
  • ต่อไปก็กำหนด core node ในที่นี้เลือกเป็น 2
  • กำหนด Cluster termination time เพื่อให้ Cluster terminate อัตโนมัติเมื่อถึงเวลาที่กำหนดไว้
  • กำหนด EC2 Keypair
  • กดสร้าง Cluster รอจน status เปลี่ยนจาก starting เป็น waiting
  • แก้ไข EC2 security group คลิกที่ primary node (ที่มีเส้นใต้)
  • คลิกที่ edit inbound rule
  • แก้ไขให้เป็น My IP แล้วกด save rules
  • เมื่อแก้ไข security rules เรียบร้อย ให้ทำการ connect EMR ผ่าน SSH
  • มีขั้นตอนคือ กดเลือก Connect to the Primary node using SSH ที่ cluster ทำการ copy ตัว ssh
  • นำมาวางใน Terminal (Mac) หรือ Powershell (Window) หาก connect สำเร็จจะได้ผลตามภาพ

2️⃣ โหลดข้อมูลลง Hive ในรูปแบบ CSV และ Parquet

ต่อไป เราจะอัพโหลดข้อมูลผ่าน Hue และสร้างตาราง CSV และ Parquet ผ่าน Hive

  • ขั้นตอนแรกเราจะล็อกอินเข้า Hue (ระวัง เพราะใส่ password ได้เพียงครั้งเดียวเท่านั้น)
  • ทำการอัพโหลดไฟล์ data ขึ้นไปที่ /user/hadoop
  • ตรวจสอบใน directory ว่าไฟล์ข้อมูลอยู่บน HDFS เรียบร้อยแล้ว
  • สร้างตาราง CSV และ Parquet บน Hive ใน Terminal (Mac) หรือใน Powershell (Window)
CREATE TABLE amazon_reviews_csv (
user_id STRING,
parent_asin STRING,
title STRING,
text STRING,
rating INT
) ROW FORMAT DELIMITED 
FIELDS TERMINATED BY ',' 
STORED AS TEXTFILE;
  • โหลดข้อมูลเข้าไปในตารางที่สร้างไว้
LOAD DATA INPATH 'hdfs:///user/hadoop/data.csv' INTO TABLE amazon_reviews_csv;
สร้างตาราง CSV และโหลดข้อมูลจากไฟล์เข้าไปในตารางที่สร้างไว้
  • สร้างตาราง Parquet ที่มีข้อมูลเหมือนกับตารางก่อนหน้าทุกอย่าง เพื่อนำมาใช้เปรียบเทียบกัน
CREATE TABLE amazon_reviews_parquet 
 STORED AS PARQUET 
 AS SELECT * FROM amazon_reviews_csv;
สร้างตาราง Parquet จากตาราง CSV

เพียงเท่านี้เราก็จะมีตาราง 2 ตารางแล้ว


3️⃣ รัน Query และจับเวลา

ขั้นตอนนี้จะทำบน Zeppelin ซึ่งเป็น notebook สำหรับรันโค้ด ก่อนอื่นต้องตั้งค่า user ก่อน ดังนี้

sudo su -
cd /etc/zeppelin/conf
cp shiro.ini.template shiro.ini
vi shiro.ini
  • เพิ่ม user hadoop และ password ในไฟล์ shiro.ini แล้วเซฟไฟล์ให้เรียบร้อยก่อนออก
  • จากนั้นทำการ restart Zeppelin
systemctl restart zeppelin
  • เข้า Zeppelin ผ่านหน้า Application ใน EMR ทำการ log in ใน Zeppelin ด้วย username และ password ที่เราเพิ่มเข้าไป
  • เข้าไปปรับแก้การตั้งค่าในส่วนของ interpreter เพื่อทำให้ User ที่ Login เข้ามาเชื่อมโยงกับ user ที่มีอยู่ในระบบ hadoop โดยเลือกที่เมนู interpreter เลื่อนลงมาที่ spark กด edit แล้วตั้งค่าดังรูป แล้วกด save ก็จะใช้ notebook ได้
  • จากนั้นเริ่มทำการเปรียบเทียบ query
from pyspark.sql import SparkSession
import time

# สร้าง SparkSession พร้อม Hive Support
spark = SparkSession.builder \
    .appName("Compare CSV vs Parquet") \
    .enableHiveSupport() \
    .getOrCreate()

# คำสั่ง SQL
query = "SELECT parent_asin, AVG(rating) FROM {} GROUP BY parent_asin"

# Query CSV
start_time = time.time()
df_csv = spark.sql(query.format("amazon_reviews_csv"))
df_csv.show()
csv_time = time.time() - start_time
print(f"⏳ CSV Query Time: {csv_time:.2f} sec")

# Query Parquet
start_time = time.time()
df_parquet = spark.sql(query.format("amazon_reviews_parquet"))
df_parquet.show()
parquet_time = time.time() - start_time
print(f"⚡ Parquet Query Time: {parquet_time:.2f} sec")

4️⃣ วิเคราะห์ผลลัพธ์

ผลลัพธ์ของการ Query โดยใช้ CSV format

ผลลัพธ์ของการ Query โดยใช้ Parquet format

ลอง query แบบเลือกทุกคอลัมน์ดูบ้าง

  • ผลลัพธ์ที่ได้คือ
ผลลัพธ์ของการ Query โดยใช้ CSV format

ผลลัพธ์ของการ Query โดยใช้ Parquet format

จากผลลัพธ์ที่ได้ พบว่า format ของไฟล์มีผลต่อความเร็วของการ query ในการ query ข้อมูลชุดเดียวกันและใช้ query เดียวกัน เวลาที่ใช้ใน text file (csv) ใช้ไป 7.29 วินาที ในขณะที่ parquet file ใช้เพียง 1.82 วินาที การใช้ Parquet ลดเวลา Query ลง 75.03% หรือในการ query อีกคำสั่ง เวลาที่ใช้ใน text file (csv) ใช้ไป 7.68 วินาที ในขณะที่ Parquet File ใช้เวลาเพียง 1.07 วินาทีเท่านั้น การใช้ Parquet ลดเวลา Query ลง 86.07%


File format รูปแบบอื่นๆ

นอกจาก Parquet file และ TEXTFILE แล้ว Apache Hive ยัง support ไฟล์รูปแบบอื่นๆ อาทิ RCFile, Avro File หรือ ORC File ซึ่งมีลักษณะเฉพาะตัวที่แตกต่างกัน หากศึกษาลักษณะเฉพาะตัวของไฟล์แต่ละชนิดให้เหมาะสมกับความต้องการ ไม่ว่าจะเป็นในแง่ของการทำงานหรือการจัดเก็บข้อมูล ก็จะสามารถช่วยเพิ่มประสิทธิภาพการใช้งานได้เป็นอย่างดี


References

บทความนี้เป็นส่วนหนึ่งของรายวิชา Bigdata คณะวิทยาศาสตร์ สาขาวิทยาการข้อมูล มหาลัยศรีนครินทรวิโรฒ เขียนโดย นางสาวคีริน โสภณวัฒนากร รหัสนิสิต 66XXXXXX140

Leave a comment