วิธีที่เร็วที่สุดในการเขียนเอกสารจำนวนมากไปยัง Firestore คืออะไร?


คำตอบ:


26

TL; DR: วิธีที่เร็วที่สุดในการสร้างวันที่จำนวนมากบน Firestore คือการดำเนินการเขียนแต่ละแบบคู่ขนาน

การเขียนเอกสาร 1,000 ฉบับไปที่ Firestore ใช้เวลา:

  1. ~105.4s เมื่อใช้การดำเนินการเขียนแต่ละรายการตามลำดับ
  2. ~ 2.8s เมื่อใช้ (2) การดำเนินการเขียนแบบแบตช์
  3. ~ 1.5s เมื่อใช้การดำเนินการเขียนเดี่ยวแบบขนาน

มีวิธีการทั่วไปสามวิธีในการดำเนินการเขียนจำนวนมากบน Firestore

  1. ดำเนินการเขียนแต่ละรายการตามลำดับ
  2. ใช้การดำเนินการเขียนเป็นชุด
  3. การดำเนินการเขียนแต่ละรายการพร้อมกัน

เราจะตรวจสอบในลำดับต่อไปนี้โดยใช้อาร์เรย์ของข้อมูลเอกสารแบบสุ่ม


การดำเนินการเขียนตามลำดับส่วนบุคคล

นี่เป็นวิธีที่ง่ายที่สุดที่เป็นไปได้:

async function testSequentialIndividualWrites(datas) {
  while (datas.length) {
    await collection.add(datas.shift());
  }
}

เราเขียนเอกสารแต่ละฉบับจนกว่าเราจะเขียนเอกสารทุกฉบับ และเรารอให้การดำเนินการเขียนแต่ละครั้งเสร็จสิ้นก่อนที่จะเริ่มในการเขียนครั้งต่อไป

เขียน 1,000 เอกสารใช้เวลาประมาณ 105 วินาทีกับวิธีการนี้เพื่อให้ผ่านคือประมาณ10 เอกสารเขียนต่อวินาที


ใช้การดำเนินการเขียนเป็นชุด

นี่คือทางออกที่ซับซ้อนที่สุด

async function testBatchedWrites(datas) {
  let batch = admin.firestore().batch();
  let count = 0;
  while (datas.length) {
    batch.set(collection.doc(Math.random().toString(36).substring(2, 15)), datas.shift());
    if (++count >= 500 || !datas.length) {
      await batch.commit();
      batch = admin.firestore().batch();
      count = 0;
    }
  }
}

คุณจะเห็นว่าเราสร้างBatchedWriteวัตถุโดยการโทรbatch()เติมให้เต็มความจุสูงสุดถึง 500 เอกสารแล้วเขียนไปที่ Firestore เราตั้งชื่อเอกสารที่สร้างขึ้นซึ่งมีแนวโน้มว่าจะไม่ซ้ำกัน (ดีพอสำหรับการทดสอบนี้)

เขียน 1,000 เอกสารใช้เวลาประมาณ 2.8 วินาทีกับวิธีการนี้เพื่อให้ผ่านคือประมาณ357 เขียนเอกสารต่อวินาที

ค่อนข้างเร็วกว่าการเขียนเรียงตามลำดับ ในความเป็นจริง: นักพัฒนาจำนวนมากใช้วิธีนี้เพราะพวกเขาคิดว่ามันเร็วที่สุด แต่เนื่องจากผลลัพธ์ข้างต้นแสดงให้เห็นว่าสิ่งนี้ไม่เป็นความจริง และรหัสนั้นซับซ้อนที่สุดเนื่องจากข้อ จำกัด ด้านขนาดสำหรับแบทช์


การดำเนินการเขียนแต่ละรายการแบบขนาน

เอกสารของ Firestore บอกสิ่งนี้เกี่ยวกับประสิทธิภาพในการเพิ่มข้อมูลจำนวนมาก :

สำหรับการป้อนข้อมูลจำนวนมากให้ใช้ไลบรารีไคลเอนต์เซิร์ฟเวอร์ที่มีการเขียนแต่ละรายการแบบขนาน การเขียนแบบแบตช์ทำได้ดีกว่าการเขียนแบบต่อเนื่อง แต่ไม่ดีกว่าการเขียนแบบขนาน

เราสามารถนำไปทดสอบกับรหัสนี้:

async function testParallelIndividualWrites(datas) {
  await Promise.all(datas.map((data) => collection.add(data)));
}

รหัสนี้เตะการaddดำเนินการให้เร็วที่สุดเท่าที่จะทำได้จากนั้นใช้Promise.all()ในการรอจนกว่าจะเสร็จสิ้นทั้งหมด ด้วยวิธีนี้การดำเนินการสามารถทำงานแบบขนาน

เขียน 1,000 เอกสารใช้เวลาประมาณ 1.5 วินาทีด้วยวิธีการนี้เพื่อให้ผ่านคือประมาณ667 เขียนเอกสารต่อวินาที

ความแตกต่างนั้นไม่ค่อยดีเท่ากันระหว่างสองวิธีแรก แต่ก็ยังเร็วกว่าการเขียนแบบแบทช์มากกว่า 1.8 เท่า


หมายเหตุเล็กน้อย:

  • คุณสามารถค้นหารหัสเต็มของการทดสอบนี้ได้ที่Github Github
  • ในขณะที่การทดสอบเสร็จสิ้นด้วย Node.js คุณมีโอกาสที่จะได้รับผลลัพธ์ที่คล้ายคลึงกันในทุกแพลตฟอร์มที่ Admin SDK รองรับ
  • อย่าดำเนินการแทรกจำนวนมากโดยใช้ SDK ไคลเอ็นต์เนื่องจากผลลัพธ์อาจแตกต่างกันมากและคาดการณ์ได้น้อยกว่ามาก
  • ตามปกติประสิทธิภาพที่แท้จริงขึ้นอยู่กับเครื่องของคุณแบนด์วิดท์และเวลาแฝงของการเชื่อมต่ออินเทอร์เน็ตและปัจจัยอื่น ๆ ขึ้นอยู่กับสิ่งที่คุณอาจเห็นความแตกต่างในความแตกต่างด้วยแม้ว่าฉันคาดว่าการสั่งซื้อจะยังคงเหมือนเดิม
  • หากคุณมีค่าผิดปกติใด ๆ ในการทดสอบของคุณเองหรือค้นหาผลลัพธ์ที่แตกต่างอย่างสิ้นเชิงให้แสดงความคิดเห็นด้านล่าง
  • ชุดการเขียนเป็นอะตอม ดังนั้นหากคุณมีการอ้างอิงระหว่างเอกสารและเอกสารทั้งหมดจะต้องเขียนหรือไม่ต้องเขียนเลยคุณควรใช้การเขียนแบบแบทช์

1
นี่เป็นเรื่องที่น่าสนใจมากขอบคุณสำหรับการทำงาน! OOC คุณทดสอบการเขียนแบทช์แบบขนานหรือไม่? เห็นได้ชัดว่าในกรณีนี้คุณจะต้องแน่ใจมากขึ้นเพื่อหลีกเลี่ยงเอกสารใด ๆ ที่อยู่ในทั้งสองชุด
robsiemb

1
ฉันกำลังจะทดสอบการเขียนแบบแบทช์แบบขนาน แต่หมดโควต้า (เป็นโครงการฟรีและฉันขี้เกียจเกินกว่าจะอัพเกรด) วันนี้เป็นวันอื่นดังนั้นฉันอาจลองทำและอัปเดตคำตอบถ้ามันสำคัญ
Frank van Puffelen

2
@robsiemb ฉันเพิ่งทดสอบด้วยการเขียนแบทช์แบบขนานเกินไป ประสิทธิภาพนั้นคล้ายกับการเขียนแบบขนานแต่ละอันดังนั้นฉันจะบอกว่ามันถูกโยงไว้เป็นครั้งแรกในการทดสอบของฉัน ฉันคาดหวังว่าการเขียนแบบแบทช์อาจลดลงเร็วขึ้นเนื่องจากลักษณะการเขียนที่แบ็คเอนด์ เมื่อรวมกับรหัสที่ซับซ้อนมากขึ้นฉันยังคงแนะนำให้ใช้เฉพาะกับอะตอมมิกของพวกเขาเท่านั้นและไม่ใช่ข้อได้เปรียบด้านประสิทธิภาพที่รับรู้ แต่ไม่มีอยู่จริง
Frank van Puffelen

@ FrankankPuffelen การเขียนแบบขนานจะเร็วขึ้นหากฉัน "ตั้งค่า" เอกสารแทน "เพิ่ม" เอกสาร? ฉันหมายถึง db.collection ('เมือง'). doc ('LA'). set (data) แทน db.collection ('เมือง'). เพิ่ม (data)
alek6dj

การโทรadd()ไม่ได้ทำอะไรมากไปกว่าการสร้าง ID เฉพาะ (ฝั่งไคลเอ็นต์ล้วน ๆ ) ตามด้วยการset()ดำเนินการ ดังนั้นผลลัพธ์ควรเหมือนกัน หากนั่นไม่ใช่สิ่งที่คุณสังเกตเห็นให้โพสต์คำถามใหม่ด้วยตัวพิมพ์เล็ก ๆ น้อย ๆ ที่ทำซ้ำสิ่งที่คุณได้ลอง
Frank van Puffelen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.