ไฟล์ JSON ใหญ่เปิดไม่ได้? เลือกเครื่องมือให้ถูกตามขนาด
สรุปสำคัญ: ไฟล์ส่งออก JSON ขนาดหลายสิบ MB มักทำให้โปรแกรมแก้ไขข้อความและเครื่องมือออนไลน์ค้าง ทั้งที่การแยกวิเคราะห์ใช้เวลาเพียงไม่กี่ร้อยมิลลิวินาที เราวัดเวลาและหน่วยความจำในแต่ละขั้นจากตัวอย่าง 45 MB จำนวน 500,000 ระเบียน ชี้ให้เห็นว่าต้นทุนจริงอยู่ที่จำนวนบรรทัดและโหนด พร้อมตารางเลือกเครื่องมือตามขนาดไฟล์: ดูออนไลน์ บรรทัดคำสั่ง การประมวลผลแบบสตรีม และแอปเดสก์ท็อป

ไฟล์ JSON 45 MB แยกวิเคราะห์เสร็จใน 249 มิลลิวินาที ครึ่งนาทีที่คุณรอมาจากการเรนเดอร์ข้อความห้าล้านบรรทัดและโหนดต้นไม้ 3.5 ล้านโหนด สับสนสองเรื่องนี้แล้วคุณจะโทษผิดคนทุกครั้ง
หนึ่ง: วัดก่อน — การแยกวิเคราะห์ไม่เคยเป็นคอขวด
ดับเบิลคลิกไฟล์ส่งออก .json หลายสิบ MB เห็นโปรแกรมแก้ไขหมุนวนสามสิบวินาที สัญชาตญาณบอกว่า "การแยกวิเคราะห์ JSON ช้า" แต่การวัดจริงบอกตรงกันข้าม บนเครื่องของเรา (Node 22) เราสร้างตัวอย่าง 500,000 ระเบียน ระเบียนละห้าฟิลด์ (id, email, active, score, tags) ขนาด 45 MB ในรูปแบบกระชับ:
| การทำงาน | ผลการวัด |
|---|---|
JSON.parse แบบเต็ม |
249 ms |
JSON.stringify(data, null, 2) — เอาต์พุตจัดรูป |
215 ms |
| ข้อความหลังจัดรูป | 71 MB, 5,000,001 บรรทัด |
| โหนดต้นไม้รวม (ระเบียน + ฟิลด์) | ประมาณ 3,500,001 |
| RSS ของโปรเซส Node หลังแยกวิเคราะห์ | 313 MB (ราว 7 เท่าของขนาดไฟล์) |
การแยกวิเคราะห์จบในหนึ่งในสี่วินาที ตัวแยกวิเคราะห์ทำงานเสร็จก่อนที่คุณจะปล่อยเมาส์ ทุกวินาทีหลังจากนั้นหมดไปกับชั้น "แสดงผลให้คนดู": โปรแกรมแก้ไขต้องจัดวางห้าล้านบรรทัด ทำไฮไลต์ไวยากรณ์ทีละบรรทัด และเก็บบัฟเฟอร์ undo; ตัวดูต้นไม้ต้องสร้างอิลิเมนต์ DOM ให้ครบทั้ง 3.5 ล้านโหนด — และเบราว์เซอร์สะดุดราวหนึ่งแสนโหนด เสียการตอบสนองก่อนถึงหนึ่งล้านนานแสนนาน
ข้อสรุปชี้ไปทางที่ต่างออกไปโดยสิ้นเชิง: หยุดต่อสู้กับการเรนเดอร์ — เปลี่ยนไปใช้เครื่องมือที่ไม่เรนเดอร์ทุกอย่างพร้อมกัน
สอง: ทำไมถึงค้าง — จำนวนบรรทัดและโหนดต่างหากคือต้นทุนจริง
ขนาดไฟล์เป็นเพียงผิวนอก ตัวเลขที่ไปล้มเครื่องมือคือสองตัวเลขที่ได้มา:
- จำนวนบรรทัด JSON กระชับ 45 MB พอจัดรูปกลายเป็นห้าล้านบรรทัด ไม่ว่าคุณจะดูส่วนไหน โปรแกรมแก้ไขต้องสร้างโครงสร้างบรรทัดของทั้งไฟล์ก่อน เคลียร์สถานะไฮไลต์ และจัดสรรบัฟเฟอร์ — ต้นทุนแปรผันตามจำนวนบรรทัดรวม
- จำนวนโหนด ห้าแสนระเบียน × (หนึ่งอ็อบเจกต์ + ห้าฟิลด์) เท่ากับ 3.5 ล้านโหนด ตัวดูใดก็ตามที่สร้างต้นไม้ทั้งต้นก่อนแสดงผล ต้องจ่ายหน่วยความจำและเวลาเท่ากันหมด — ไม่ว่าคุณจะกางหนึ่งกิ่งหรือกางทุกกิ่ง
จากนี้ได้ข้อสรุปสองข้อที่ขัดสัญชาตญาณ จัดรูปก่อนดูคือแบกหาม — ไฟล์โตจาก 45 เป็น 71 MB จำนวนบรรทัดโตสี่สิบเท่า เป็นแรงกดส่วนเกินล้วน ๆ ต่อเครื่องมือ ส่งไฟล์ผ่าน cat เข้าเทอร์มินัลก็แบกหามเช่นกัน — บัฟเฟอร์สกรอลล์กลายเป็นคอขวดใหม่ ถ้าแค่อยากดูไบต์แรก ๆ head -c 2000 ก็พอ
สาม: เลือกเครื่องมือตามขนาด — ตารางตัดสินใจ
ขนาดต่างกันต้องใช้เครื่องมือต่างกันโดยสิ้นเชิง เมื่อรวมผลวัดข้างต้นกับคำแนะนำที่เผยแพร่ (OpenFormatter วางโซนสบายของเครื่องมือออนไลน์ที่ 2-5 MB; PureJSON ประมาณหน่วยความจำหลังแยกวิเคราะห์เอกสาร 500 MB ที่ 2-4 GB) ได้ตารางนี้:
| ขนาดไฟล์ | ทางเลือกแรก | เหตุผล |
|---|---|---|
| < 2 MB | เครื่องมือออนไลน์ตัวไหนก็ได้ | เข้าถึงทันที; ดูต้นไม้ + ตรวจสอบแบบ /parse ในขั้นเดียว |
| 2 – 20 MB | โปรแกรมแก้ไขบนเครื่อง (VS Code) หรือเครื่องมือในเบราว์เซอร์ | เครื่องมือออนไลน์เริ่มถดถอย; ประมวลผลบนเครื่องไม่ส่งอะไรไปไหน |
| 20 – 100 MB | สำรวจด้วย jq บน CLI + ตัวดูต้นไม้แบบเวอร์ชวลไลซ์ | โปรแกรมแก้ไขเริ่มติดขัด; jq ดึงข้อมูลส่วนไหนก็ได้ในไม่กี่วินาที |
| 100 MB – 1 GB | jq --stream / ijson ประมวลผลแบบสตรีม |
หน่วยความจำของการแยกวิเคราะห์แบบปกติโตถึง ~7 เท่าของไฟล์ ไม่พอก็สตรีม |
| > 1 GB หรือเพิ่มต่อเนื่อง | เปลี่ยนฟอร์แมต: NDJSON / CSV / Parquet | อาร์เรย์ยักษ์ตัวเดียวต้องแยกวิเคราะห์จนจบกว่าระเบียนแรกจะใช้ได้ ปัญหาอยู่ที่ฟอร์แมตเอง |
เครื่องมือ /parse ของเว็บนี้ครอบขั้นแรก: ดูต้นไม้และตรวจสอบ ไฟล์ที่ใหญ่กว่านั้นเป็นหน้าที่ของ แอปเดสก์ท็อป เพื่อไม่ให้ข้อมูลหลายสิบ MB ถูกวางลงในหน้าเว็บ
สี่: อย่าเปิดไฟล์ — ถามโครงสร้างก่อน
เจอ JSON ใหญ่ที่ไม่คุ้นเคย ก้าวแรกไม่ใช่การเปิด แต่คือใช้เวลาไม่กี่วินาทีสำรวจรูปร่าง jq ตอบสามคำถามในราว 200 ms:
# ด้านบนเป็นอาร์เรย์หรืออ็อบเจกต์? มีกี่ระเบียน?
jq 'if type == "array" then {type: "array", count: length} else {type: "object", keys: (keys|length)} end' huge.json
# ระเบียนแรกหน้าตาเป็นอย่างไร (ดูตัวเดียว ไม่ท่วมจอ)?
jq '.[0]' huge.json | head -40
# ชื่อฟิลด์ทั้งหมด (เอาจากระเบียนแรก)
jq '.[0] | keys' huge.json
พอรู้โครงสร้างแล้ว ความต้องการส่วนใหญ่ย่อลงเหลือ "ดึงฟิลด์หนึ่งตัว" — ไม่จำเป็นต้องเปิดไฟล์เลย เช่น ต้องการอีเมลของผู้ใช้ทุกคน:
jq -r '.[].email' huge.json | less
# ซ้อนตัวกรองเพิ่ม
jq -r '.[] | select(.active == true) | .email' huge.json
กฎง่าย ๆ: อยาก "ดู" ใช้ตัวดูที่เรนเดอร์แบบเวอร์ชวลไลซ์ อยาก "ค้นและดึง" ใช้ jq อย่าใช้เครื่องมือเดียวทำทั้งสองบทบาท
ห้า: หน้าผาของหน่วยความจำ — โหมดปกติกับสตรีม ต่างกัน 150 เท่า
จากตัวอย่าง 45 MB เดียวกัน /usr/bin/time -v วัดหน่วยความจำสูงสุดของ jq สองโหมด:
| โหมด | คำสั่ง | หน่วยความจำสูงสุด (RSS) | เวลา |
|---|---|---|---|
| ปกติ (โหลดทั้งหมด) | jq '.[0].email' sample.json |
542 MB | 0.7 s |
| สตรีม | jq --stream 'select(.[0][1]=="email") | .[1]' sample.json |
3.6 MB | 2.5 s |
โหมดปกติอ่านไฟล์ทั้งไฟล์และสร้างกราฟอ็อบเจกต์ ยอด 542 MB ยืนยันกฎ "กราฟอ็อบเจกต์ ≈ 7-12 เท่าของขนาดข้อความ" --stream กินอินพุตทีละโทเค็น คุมหน่วยความจำไว้ระดับหลักเดียว MB — แลกกับเวลารวมที่นานขึ้น พ้นขีดกิกะไบต์ไปแล้ว ความต่างนี้คือเส้นแบ่งระหว่าง "รันได้" กับ "ถูก OOM killer ฆ่า":
# ไฟล์ใหญ่กว่าหน่วยความจำ: --stream คือโหมดเดียวที่ไม่เคยโหลดทั้งหมด
jq --stream -n 'fromstream(1|truncate_stream(inputs))' huge.json
ฝั่ง Python ที่เทียบเท่าคือ ijson: ijson.items(f, 'item') คายอิลิเมนต์อาร์เรย์ทีละตัวด้วยหน่วยความจำคงที่เช่นกัน ราคาร่วมของเครื่องมือกลุ่มนี้คือ สละการเข้าถึงแบบสุ่ม — สตรีมเดินหน้าผ่านครั้งเดียวจบ จะผ่านรอบสองต้องอ่านไฟล์ซ้ำ
หก: เบราว์เซอร์ไปได้ถึงไหน — ขอบเขตของการประมวลผลบนเครื่อง
เครื่องมือออนไลน์ใช้ได้ แต่มีขอบเขต แท็บเบราว์เซอร์สมัยใหม่มีหน่วยความจำราว 1-4 GB ไฟล์ 45 MB ที่แยกวิเคราะห์เป็นกราฟบวกต้นไม้มักรอด หลายร้อย MB เริ่มชนขอบหน้าผา เลือกตัวดูออนไลน์แล้วขอสามอย่าง:
- ประมวลผลบนเครื่องทั้งหมด (ข้อความที่วางไม่เดินทางไปเซิร์ฟเวอร์) — ทั้งปกป้องข้อมูลและประหยัดเวลาอัปโหลด เครื่องมือทุกตัวบนเว็บนี้รันในเบราว์เซอร์ล้วน ๆ และใช้งานออฟไลน์ได้;
- แยกวิเคราะห์ใน Web Worker — เธรดหลักไม่แข็ง งงก็เสียแค่แท็บ ไม่ใช่ทั้งเบราว์เซอร์;
- ต้นไม้เป็นแบบเวอร์ชวลไลซ์หรือกางเกียจคร้าน — กิ่งที่พับอยู่แทบไม่มีต้นทุน เรนเดอร์เท่าที่กางออก
ในเว็บนี้: /parse เหมาะกับการสำรวจโครงสร้างและหาตำแหน่งข้อผิดพลาดในไฟล์ถึงระดับไม่กี่สิบ MB กว่านั้นคือ jq หรือแอปเดสก์ท็อป ส่วนเบราว์เซอร์เก็บไว้สำหรับชิ้นเล็ก ๆ
เจ็ด: เลือกฟอร์แมตถูก ปัญหาหายครึ่งหนึ่ง
ถ้าคุณมีอิทธิพลต่อการสร้างไฟล์ ตัวดูที่ดีกว่าคือยาผิดโรค — จัดการให้มันไม่โตขึ้นเป็น "อาร์เรย์ยักษ์ตัวเดียว":
- NDJSON/JSONL: หนึ่งบรรทัดต่อระเบียน เพิ่มข้อมูลไม่ต้องเขียนไฟล์ใหม่ทั้งไฟล์
head,grep,tail,splitใช้ได้เลย ไฟล์ถูกตัดกลางคันเสียแค่บรรทัดสุดท้าย คู่มือ JSONL ของเรามีวิธีไล่บั๊กบรรทัดเสียอย่างละเอียด - ส่งออกแบบแบ่งหน้า: API ที่คืน 100,000 ระเบียนควรรับพารามิเตอร์แบ่งหน้า — ครั้งละ 100 ระเบียนเป็นมิตรกับทั้งสองฝ่าย
- ข้อมูลแบบตารางไม่ควรเป็น JSON: หนึ่งระเบียนต่อบรรทัด ฟิลด์คงที่ไม่มีการซ้อน — นั่นคือตาราง CSV หรือ Parquet เล็กกว่าและระบบนิเวศสมบูรณ์กว่า
ตัวเลขที่ควรจำ: ตัดอาร์เรย์ 500,000 ระเบียนออกเป็นสองท่อน ท่อนหน้ายังเป็นไฟล์ NDJSON ที่ใช้ได้ (รอดครึ่งหนึ่งของระเบียน) แต่อาร์เรย์ยักษ์ตัวเดียวที่เทียบเท่าพังทั้งชุด กู้คืนได้ 500 จาก 501 ระเบียนดีกว่าศูนย์
แปด: เช็กลิสต์
- สำรวจโครงสร้างก่อนด้วย
jq '.[0] | keys'หรือตัวอย่าง 500 ระเบียน; - อย่าจัดรูปเพียงเพื่อเปิดไฟล์ — บรรทัดเท่าตัวทำให้ช้าลงอย่างเดียว;
- ต่ำกว่า 2 MB: ดูต้นไม้ออนไลน์ เกิน 20 MB: บรรทัดคำสั่ง เกิน 1 GB:
--streamหรือ ijson เสมอ; - ยืนยันว่าเครื่องมือออนไลน์ประมวลผลบนเครื่อง (ข้อความที่วางไม่หลุดออกจากเบราว์เซอร์);
- ถ้าคุณคุมฝั่งสร้างไฟล์ เปลี่ยนไปใช้ NDJSON หรือแบ่งหน้า ตัดอาร์เรย์ยักษ์ตั้งแต่ต้นทาง
คำถามที่พบบ่อย
ทำไมโปรแกรมแก้ไขเปิด JSON ใช้เวลาหลายสิบวินาที ทั้งที่โปรแกรมแยกวิเคราะห์ได้ใน 200 ms?
การแยกวิเคราะห์คือโค้ดเนทีฟที่เปลี่ยนข้อความเป็นโครงสร้างข้อมูล: 249 ms จากตัวอย่าง 45 MB ของเรา โปรแกรมแก้ไขติดที่การนำเสนอ: ห้าล้านบรรทัดต้องจัดวาง ไฮไลต์ และเก็บบัฟเฟอร์ undo; ต้นไม้สร้าง DOM 3.5 ล้านโหนด ตัวดูแบบเวอร์ชวลไลซ์หรือดึงข้อมูลตรง ๆ ด้วย jq เลี่ยงทั้งหมดได้
jq เจอ JSON เกิน 1 GB จะหน่วยความจำล้นไหม?
โหมดปกติจะล้น: มันโหลดทั้งเอกสาร กราฟอ็อบเจกต์พุ่งถึง 7-12 เท่าของขนาดไฟล์ ใส่ --stream แล้วอินพุตถูกกินทีละโทเค็น: ทดสอบ 45 MB ได้ยอดสูงสุด 3.6 MB และหน่วยความจำแบนราบไม่ว่าไฟล์จะใหญ่แค่ไหน — แลกกับการเดินผ่านตามลำดับเพียงครั้งเดียว
เครื่องมือ JSON ออนไลน์รับไฟล์ได้ใหญ่แค่ไหน?
ส่วนใหญ่สบายถึง 2-5 MB และเสื่อมชัดเจนหลัง 10 MB เพดานแข็งคือหน่วยความจำของแท็บ (ราว 1-4 GB) แต่ระดับไม่กี่สิบ MB การรอแยกวิเคราะห์และสร้างต้นไม้ก็ทรมานแล้ว เกิน 20 MB เปลี่ยนไปใช้เครื่องมือบนเครื่องหรือบรรทัดคำสั่ง
อยากดูค่าฟิลด์ตัวเดียวใน JSON มหึมา ทำอย่างไร?
ดึงด้วย jq โดยไม่เปิดไฟล์: jq -r '.[].email' huge.json พิมพ์อีเมลทุกตัว ใส่ตัวกรองได้ jq -r '.[] | select(.active == true) | .email' ดูระเบียนแรก ๆ ใช้ jq '.[0:5]' huge.json — เร็วกว่าการเปิดไฟล์หลายเท่าตัว
จัดรูปก่อนแล้วค่อยเปิดช่วยไหม?
ไม่ช่วย การจัดรูปเปลี่ยน 45 MB กระชับเป็น 71 MB และบรรทัดเดียวเป็นห้าล้านบรรทัด เพิ่มภาระล้วน ๆ ให้โปรแกรมแก้ไขและตัวดู เก็บการจัดรูปไว้สำหรับสิ่งที่คนจะอ่าน — และเฉพาะเมื่อไฟล์เล็กพอ