การสร้างคลังข้อมูลสภาพอากาศ ตอนที่ 1: โหลดข้อมูลสภาพอากาศ 1 ล้านล้านแถวเข้า TimescaleDB
ความหมายของสิ่งที่เรากำลังทำ
เหตุผลที่สร้างคลังข้อมูลสภาพอากาศ
- มีแนวคิดว่าการรวบรวมและวิเคราะห์ข้อมูลสภาพอากาศย้อนหลังจากทั่วโลกเพื่อตรวจหาสัญญาณของการเปลี่ยนแปลงสภาพภูมิอากาศน่าจะเป็นประโยชน์
- หากมีคลังข้อมูลสภาพอากาศขนาดใหญ่ ก็จะสามารถดูได้เป็นรายภูมิภาคว่า จาการ์ตาร้อนขึ้นจริงหรือไม่ หรือพายุรุนแรงขึ้นหรือไม่ รวมถึงชิลีกำลังร้อนขึ้นโดยรวม หรือมีเมฆมากขึ้นหรือไม่
- จากสิ่งนี้ เราสามารถระบุได้ว่าพื้นที่ใดบนโลกเผชิญกับการเปลี่ยนแปลงสภาพภูมิอากาศมากที่สุด และเกิดการเปลี่ยนแปลงในรูปแบบใดบ้าง
- เพื่อทำการวิเคราะห์ลักษณะนี้ในระดับโลก จำเป็นต้องเพิ่มความเร็วในการสืบค้นของคลังข้อมูล และปริมาณข้อมูลก็มีขนาดมหาศาลมาก
- ขั้นตอนแรกคือการโหลดข้อมูลเข้า PostgreSQL โดยดูมีแนวโน้มดีที่จะใช้ TimescaleDB เพื่อเพิ่มความเร็วของคิวรีแบบอนุกรมเวลา และใช้ PostGIS เพื่อเพิ่มความเร็วของคิวรีเชิงภูมิสารสนเทศ
แนะนำข้อมูล
- ใช้ข้อมูลผลิตภัณฑ์ climate reanalysis ของ ERA5 ไม่ใช่ข้อมูลการสังเกตจริงโดยตรง
- ERA5 คือผลลัพธ์จากการรันแบบจำลองภูมิอากาศที่ถูกจำกัดด้วยข้อมูลการสังเกต ดังนั้นบริเวณที่มีข้อมูลสังเกตมากจะคล้ายกับข้อมูลจริง ส่วนบริเวณที่ไม่มีข้อมูลสังเกตจะยังคงมีความสอดคล้องทางฟิสิกส์และสอดคล้องกับสถิติภูมิอากาศ
- ERA5 ให้ข้อมูลรายชั่วโมงครอบคลุมทั้งโลกตั้งแต่ปี 1940 ที่ความละเอียด 0.25 องศา โดยมีข้อมูลมากกว่า 750 ล้านแถวต่อหนึ่งตัวแปร เช่น อุณหภูมิ ปริมาณฝน ปริมาณเมฆ และความเร็วลม
- การแทรกข้อมูลลักษณะนี้เข้า relational DB อย่างรวดเร็วไม่ใช่เรื่องง่าย
วิธีแทรกข้อมูล
คำสั่ง insert แบบแถวเดียว
- เป็นวิธีที่ง่ายที่สุด แต่ช้ามาก ด้วยอัตราแทรก 3,000 รายการต่อวินาที จะใช้เวลาประมาณ 8 ปีในการโหลดข้อมูลทั้งหมด
- มี overhead สูงจากการแยกวิเคราะห์ไวยากรณ์ การตรวจสอบตาราง/คอลัมน์ แผนการรัน การล็อกตาราง การเขียนบัฟเฟอร์ การเขียนดิสก์ และการ commit
insert แบบหลายค่า
- แทรกหลายแถวด้วยคำสั่ง insert เดียว ลด overhead ของเครือข่าย การแยกวิเคราะห์ไวยากรณ์ และแผนการรัน
- psycopg3 เร็วที่สุดที่ 25,000~30,000 รายการต่อวินาที
- แต่ถึงอย่างนั้นก็ยังต้องใช้เวลาประมาณ 10 เดือนในการโหลดข้อมูลทั้งหมด
คำสั่ง copy
- เป็นวิธีที่เหมาะสำหรับการโหลดข้อมูลจำนวนมาก โดยอ่านจากไฟล์ CSV หรือไฟล์ไบนารีโดยตรง ทำให้ปรับปรุงการแยกวิเคราะห์ การวางแผน และการใช้ WAL ได้ดีขึ้น
- หากมี CSV อยู่แล้ว ก็สามารถใช้คำสั่ง copy ได้อย่างง่ายดาย
- copy ของ psycopg3 สามารถแทรกได้มากกว่า 100,000 รายการต่อวินาที และแม้รวม overhead แล้วก็ยังโหลดข้อมูลทั้งหมดได้ภายใน 3 เดือน
- เมื่อต้องแทรกด้วยความเร็วสูงเป็นเวลานานผ่าน copy จำเป็นต้องระวังคอขวดที่อาจเกิดขึ้น
copy แบบขนาน
- ทำงาน copy หลายชุดพร้อมกันเพื่อเพิ่มความเร็ว
- การแทรกลงตารางเดียวไม่ได้รับประโยชน์จากการประมวลผลแบบขนานมากนัก ดังนั้นเมื่อเกิน worker 16 ตัวก็แทบไม่มีประสิทธิภาพเพิ่มขึ้น
การใช้เครื่องมือภายนอก
- มีการ benchmark ระหว่าง pg_bulkload และ timescaledb-parellel-copy
- pg_bulkload เร็วกว่า แต่โดยพื้นฐานแล้วข้าม WAL จึงไม่ปลอดภัย
- timescaledb-parallel-copy สามารถแทรกอย่างปลอดภัยได้มากกว่า 300,000 รายการต่อวินาทีด้วย worker หลายตัว
การปรับตั้งค่า PostgreSQL
- การปิด
fsync และ full_page_writes จะช่วยหลีกเลี่ยงการเขียนดิสก์และทำให้เร็วขึ้นได้ แต่มีความเสี่ยง
- ตารางแบบ unlogged ก็ไม่ใช้ WAL จึงเร็วกว่า แต่จะถูกตัดทอนเมื่อระบบล้มเหลว และ hypertable ไม่สามารถเป็น unlogged ได้
วิธีที่ดีที่สุดคืออะไร?
- การใช้ psycopg3 ทำ
copy ตรงเข้า hypertable เป็นทางเลือกที่ดีที่สุด หากเป็นไฟล์ CSV ให้ใช้ timescaledb-parallel-copy
- การประมวลผลแบบขนานที่เหมาะสมคือ worker ราว 12~16 ตัว
- หากปิดข้อจำกัดด้านความปลอดภัยบางอย่าง อาจไปได้ถึง 460,000 รายการต่อวินาที แต่มีความเสี่ยง
- หากอัปเกรดฮาร์ดแวร์ก็อาจทำความเร็วได้มากกว่านี้
- ClickHouse อาจเร็วกว่า แต่เลือก TimescaleDB เพราะต้องการเรียนรู้ PostgreSQL
- ที่ความเร็ว 460,000 รายการต่อวินาที สามารถโหลดข้อมูลทั้งหมดได้ภายใน 20 วัน
ความเห็นของ GN⁺
- ความพยายามในการนำข้อมูล ERA5 มาใส่ใน relational DB เพื่อวิเคราะห์นั้นน่าสนใจมาก ปกติเดิมทีการวิเคราะห์ข้อมูล NetCDF โดยตรงด้วย xarray หรือ dask เป็นแนวทางที่พบได้ทั่วไป แต่ถ้าสร้างคลังข้อมูลขึ้นมา ก็จะสามารถทำคิวรีที่ซับซ้อนยิ่งขึ้นได้
- น่าประทับใจที่ฮาร์ดแวร์ของผู้เขียนเป็นสเปกเมื่อ 5 ปีก่อน แต่ยังสามารถใส่ข้อมูลได้ถึง 460,000 รายการต่อวินาที หากเป็นฮาร์ดแวร์รุ่นใหม่ ก็น่าจะไปถึง 1 ล้านรายการต่อวินาทีได้ อย่างไรก็ตาม การปิด
fsync และ full_page_writes อาจกระทบต่อความสมบูรณ์ของฐานข้อมูล จึงต้องระวัง
- ดูเหมือนความสามารถด้าน parallel processing ของ PostgreSQL จะไม่ได้ช่วยมากนักกับตารางเดี่ยว หากนำ parallel processing มารวมกับ partitioning ก็น่าจะได้ประสิทธิภาพสูงขึ้น และโซลูชันขยายแนวนอนของ Postgres อย่าง Citus ก็เป็นสิ่งที่ควรพิจารณา
- ประเด็นที่ว่า ERA5 สามารถนำมาใช้วิเคราะห์การเปลี่ยนแปลงสภาพภูมิอากาศได้นั้นน่าสนใจ เพราะช่วยให้วิเคราะห์ภูมิอากาศในอดีตของพื้นที่ที่ขาดข้อมูลการสังเกตได้ แต่ ERA5 ก็มีข้อจำกัดตรงที่เป็นผลลัพธ์จากแบบจำลอง จึงควรคำนึงถึงความไม่แน่นอน แม้จะมีการปรับแก้ด้วยข้อมูลสังเกตแล้วก็ตาม
- สำหรับแพลตฟอร์มวิเคราะห์ โดยทั่วไปมักใช้คลังข้อมูลบนคลาวด์อย่าง Snowflake หรือ BigQuery แต่การลงมือจัดการฮาร์ดแวร์เองและเรียนรู้แบบผู้เขียนก็มีคุณค่าไม่น้อย โดยเฉพาะเมื่อข้อมูลภูมิอากาศมีขนาดใหญ่มากจนย้ายขึ้นคลาวด์ได้ไม่ง่าย และก็น่าติดตามผลการวิเคราะห์จริงในอนาคต
2 ความคิดเห็น
ความเห็นของ GN+ เป็นภาษาสุภาพเหรอครับ..?
ความเห็นจาก Hacker News
สรุปได้ดังนี้:
เมื่อต้องวิเคราะห์ข้อมูลเชิงพื้นที่ สิ่งสำคัญคือต้องเข้าใจระบบพิกัด (CRS) และการฉายแผนที่ สำหรับงานเชิงพื้นที่ขนาดใหญ่ Google BigQuery ทำได้โดดเด่นที่สุด
ต้องทดลองจึงจะรู้ว่าฐานข้อมูลเชิงสัมพันธ์เหมาะกับข้อมูลอากาศแบบกริดหรือไม่
สาเหตุที่ Hypertable ใน Timescale ช้า อาจมาจากดัชนีของคอลัมน์ timestamp ที่ถูกสร้างเป็นค่าเริ่มต้น ควรข้ามการสร้างดัชนีด้วยตัวเลือก
create_default_indexes=>falseหรือสร้างดัชนีหลังจากนำเข้าข้อมูลแล้วการวิเคราะห์ยังไม่เพียงพอว่าการย้ายข้อมูลอากาศไปยัง RDBMS มีข้อดีอะไรบ้าง ใช้ Serverless + object storage ก็ให้ความเร็วในการตอบสนองที่สูงมากได้เช่นกัน
ชุดข้อมูลอากาศ/ภูมิอากาศส่วนใหญ่ เช่น ERA5 ประกอบด้วยกริดละติจูด-ลองจิจูดที่เป็นระเบียบอยู่แล้ว ดังนั้นไม่ควรทำลายโครงสร้างนั้นทั้งหมด และควรใช้เวอร์ชันที่ปรับให้เหมาะกับคลาวด์อย่าง ARCO-ERA5 แทน
หากปิด WAL ใน PostgreSQL และรันคำสั่ง
VACUUM FREEZEเป็นระยะ ก็อาจเพิ่มประสิทธิภาพการโหลดข้อมูลปริมาณมากได้อีกหากใช้ COPY ไม่ได้ การเข้ารหัสแถวข้อมูลเป็นสตริง JSON แล้วส่งเป็นพารามิเตอร์ของคิวรีเดียว พร้อมใช้
json_to_recordsetก็เป็นวิธีที่ดีเช่นกัน