แนวทางปฏิบัติแนะนำสำหรับ Cloud Firestore

ใช้แนวทางปฏิบัติแนะนำที่ระบุไว้ที่นี่เป็นข้อมูลอ้างอิงอย่างรวดเร็วเมื่อสร้างแอปพลิเคชันที่ใช้ Cloud Firestore

ตำแหน่งที่ตั้งของฐานข้อมูล

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

หากต้องการเพิ่มความพร้อมใช้งานและความทนทานของแอปพลิเคชัน ให้เลือกตำแหน่งหลายภูมิภาคและวางทรัพยากรการประมวลผลที่สำคัญในภูมิภาคอย่างน้อย 2 แห่ง

เลือกตำแหน่งระดับภูมิภาคเพื่อลดต้นทุน ลดเวลาในการตอบสนองการเขียน หากแอปพลิเคชันของคุณไวต่อเวลาในการตอบสนอง หรือใช้ร่วมกับทรัพยากร GCP อื่นๆ

รหัสเอกสาร

  • หลีกเลี่ยงรหัสเอกสาร . และ ..
  • หลีกเลี่ยงการใช้เครื่องหมายทับ / ในรหัสเอกสาร
  • อย่าใช้รหัสเอกสารที่เพิ่มขึ้นแบบเชิงเดี่ยว เช่น

    • Customer1, Customer2, Customer3, ...
    • Product 1, Product 2, Product 3, ...

    รหัสตามลําดับดังกล่าวอาจทําให้เกิดฮอตสปอตที่ส่งผลต่อเวลาในการตอบสนอง

ชื่อช่อง

  • หลีกเลี่ยงการใช้อักขระต่อไปนี้ในชื่อฟิลด์ เนื่องจากต้องมีการหลีกอักขระเพิ่มเติม

    • .
    • [ วงเล็บเปิด
    • ] วงเล็บปิด
    • * เครื่องหมายดอกจัน
    • ` แบ็กทิก

ดัชนี

ลดเวลาในการตอบสนองของการเขียน

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

  • ตั้งค่าการยกเว้นดัชนีระดับคอลเล็กชัน ค่าเริ่มต้นที่ง่ายคือปิดใช้การจัดเรียงจากน้อยไปมากและการจัดทำดัชนีอาร์เรย์ การนําค่าที่จัดทำดัชนีไว้แต่ไม่ได้ใช้งานออกยังช่วยลดต้นทุนพื้นที่เก็บข้อมูลด้วย

  • ลดจำนวนเอกสารในธุรกรรม หากต้องการเขียนเอกสารจํานวนมาก ให้พิจารณาใช้เครื่องมือเขียนไฟล์จํานวนมากแทนเครื่องมือเขียนไฟล์กลุ่มแบบอะตอม

การยกเว้นดัชนี

สําหรับแอปส่วนใหญ่ คุณสามารถใช้การจัดทำดัชนีอัตโนมัติ รวมถึงลิงก์ข้อความแสดงข้อผิดพลาดเพื่อจัดการดัชนีได้ อย่างไรก็ตาม คุณอาจต้องเพิ่มการยกเว้นช่องเดียวในกรณีต่อไปนี้

การก คำอธิบาย
ช่องสตริงขนาดใหญ่

หากมีฟิลด์สตริงที่มักเก็บค่าสตริงยาวๆ ที่คุณไม่ได้ใช้สำหรับค้นหา คุณสามารถลดค่าใช้จ่ายในการจัดเก็บได้โดยยกเว้นฟิลด์นั้นไม่ให้ได้รับการจัดทําดัชนี

อัตราการเขียนสูงไปยังคอลเล็กชันที่มีเอกสารซึ่งมีค่าตามลำดับ

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

ตัวอย่างเช่น ใน Use Case ของ IoT ที่มีอัตราการเขียนสูง คอลเล็กชันที่มีเอกสารซึ่งมีช่องการประทับเวลาอาจเข้าใกล้ขีดจํากัดการเขียน 500 ครั้งต่อวินาที

ฟิลด์ TTL

หากคุณใช้นโยบาย TTL (Time To Live) โปรดทราบว่าช่อง TTL ต้องเป็นการประทับเวลา ระบบจะเปิดใช้การจัดทำดัชนีในช่อง TTL โดยค่าเริ่มต้น ซึ่งอาจส่งผลต่อประสิทธิภาพเมื่ออัตราการเข้าชมสูงขึ้น แนวทางปฏิบัติแนะนำคือเพิ่มการยกเว้นช่องเดี่ยวสำหรับช่อง TTL

ฟิลด์อาร์เรย์หรือแผนที่ขนาดใหญ่

ฟิลด์อาร์เรย์หรือแผนที่ขนาดใหญ่อาจเข้าใกล้ขีดจํากัดของรายการดัชนี 40,000 รายการต่อเอกสาร หากคุณไม่ได้ค้นหาตามอาร์เรย์ขนาดใหญ่หรือฟิลด์แผนที่ คุณควรยกเว้นฟิลด์ดังกล่าวจากการจัดทำดัชนี

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

  • อัตราสูงสุดที่แน่นอนที่แอปจะอัปเดตเอกสารรายการเดียวได้นั้นขึ้นอยู่กับปริมาณงานเป็นอย่างมาก ดูข้อมูลเพิ่มเติมได้ที่การอัปเดตเอกสารเดียว

  • ใช้การเรียกแบบอะซิงโครนัส (หากมี) แทนการเรียกแบบซิงโครนัส การเรียกใช้แบบไม่พร้อมกันจะลดผลกระทบของเวลาในการตอบสนอง ตัวอย่างเช่น ลองพิจารณาแอปพลิเคชันที่ต้องอาศัยผลการค้นหาเอกสารและผลการค้นหาก่อนที่จะแสดงผลลัพธ์ หากการค้นหาและการค้นหาไม่มีข้อมูลที่ต้องพึ่งพากัน ก็ไม่จำเป็นต้องรอแบบซิงค์จนกว่าการค้นหาจะเสร็จสมบูรณ์ก่อนเริ่มการค้นหา

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

ธุรกรรมที่พยายามอีกครั้ง

Cloud Firestore SDK และไลบรารีไคลเอ็นต์จะพยายามทำธุรกรรมที่ดำเนินการไม่สำเร็จอีกครั้งโดยอัตโนมัติเพื่อจัดการกับข้อผิดพลาดชั่วคราว หากแอปพลิเคชันเข้าถึง Cloud Firestore ผ่าน API ของ REST หรือ RPC โดยตรงแทนที่จะผ่าน SDK แอปพลิเคชันควรใช้การพยายามทำธุรกรรมอีกครั้งเพื่อเพิ่มความน่าเชื่อถือ

การอัปเดตแบบเรียลไทม์

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

การออกแบบเพื่อรองรับการใช้งานในวงกว้าง

แนวทางปฏิบัติแนะนำต่อไปนี้อธิบายวิธีหลีกเลี่ยงสถานการณ์ที่ทำให้เกิดปัญหาการแย่งสิทธิ์

การอัปเดตเอกสารเดียว

เมื่อออกแบบแอป ให้พิจารณาความเร็วที่แอปอัปเดตเอกสารรายการเดียว วิธีที่ดีที่สุดในการระบุลักษณะประสิทธิภาพของภาระงานคือการทดสอบการโหลด อัตราสูงสุดที่แน่นอนที่แอปจะอัปเดตเอกสารรายการเดียวได้นั้นขึ้นอยู่กับปริมาณงานเป็นอย่างมาก ปัจจัยต่างๆ ได้แก่ อัตราการเขียน การแย่งกันใช้ระหว่างคำขอ และจำนวนดัชนีที่ได้รับผลกระทบ

การดำเนินการเขียนเอกสารจะอัปเดตเอกสารและดัชนีที่เกี่ยวข้อง และCloud Firestoreใช้การดำเนินการเขียนแบบซิงค์กับสัดส่วนการโหวตขั้นต่ำของข้อมูลจำลอง เมื่ออัตราการเขียนสูงมากพอ ฐานข้อมูลจะเริ่มพบการแย่งกันใช้ เวลาในการตอบสนองที่นานขึ้น หรือข้อผิดพลาดอื่นๆ

อัตราการอ่าน เขียน และลบสูงในขอบเขตเอกสารที่แคบ

หลีกเลี่ยงอัตราการอ่านหรือเขียนที่สูงเพื่อปิดเอกสารตามลําดับตัวอักษร ไม่เช่นนั้นแอปพลิเคชันจะพบข้อผิดพลาดการแย่งกันใช้ ปัญหานี้เรียกว่าฮอตสปอต และแอปพลิเคชันอาจเกิดฮอตสปอตได้หากดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้

  • สร้างเอกสารใหม่ในอัตราที่สูงมากและจัดสรรรหัสที่เพิ่มขึ้นเรื่อยๆ ของตัวเอง

    Cloud Firestore จัดสรรรหัสเอกสารโดยใช้อัลกอริทึมการกระจาย คุณไม่ควรพบฮอตสปอตในการเขียนหากสร้างเอกสารใหม่โดยใช้รหัสเอกสารอัตโนมัติ

  • สร้างเอกสารใหม่ในอัตราที่สูงในคอลเล็กชันที่มีเอกสารเพียงไม่กี่รายการ

  • สร้างเอกสารใหม่ที่มีช่องเพิ่มขึ้นแบบเชิงเดี่ยว เช่น การประทับเวลา ในอัตราที่สูงมาก

  • ลบเอกสารในคอลเล็กชันในอัตราที่สูง

  • เขียนลงในฐานข้อมูลด้วยอัตราที่สูงมากโดยไม่มีการค่อยๆ เพิ่มการเข้าชม

หลีกเลี่ยงการข้ามข้อมูลที่ลบไปแล้ว

หลีกเลี่ยงการค้นหาที่ข้ามข้อมูลที่ลบไปเมื่อเร็วๆ นี้ การค้นหาอาจต้องข้ามรายการดัชนีจํานวนมากหากมีการลบผลการค้นหาในช่วงต้นไปเมื่อเร็วๆ นี้

ตัวอย่างของภาระงานที่อาจต้องข้ามข้อมูลที่ถูกลบจำนวนมากคือภาระงานที่พยายามค้นหารายการงานเก่าสุดในคิว คําค้นหาอาจมีลักษณะดังนี้

docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
delete_batch.commit()

ทุกครั้งที่การค้นหานี้ทำงาน ระบบจะสแกนรายการดัชนีสำหรับช่อง created ในเอกสารที่เพิ่งลบ ซึ่งจะทำให้การค้นหาช้าลง

หากต้องการปรับปรุงประสิทธิภาพ ให้ใช้เมธอด start_at เพื่อค้นหาจุดเริ่มต้นที่ดีที่สุด เช่น

completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
    {'created': completed_items.get('last_completed')}).order_by(
        'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
  last_completed = doc.get('created')

if last_completed:
  delete_batch.update(completed_items.reference,
                      {'last_completed': last_completed})
  delete_batch.commit()

หมายเหตุ: ตัวอย่างด้านบนใช้ช่องที่เพิ่มขึ้นอย่างเดียว ซึ่งเป็นรูปแบบที่ไม่เหมาะสมสำหรับอัตราการเขียนสูง

การเพิ่มการเข้าชม

คุณควรค่อยๆ เพิ่มการเข้าชมคอลเล็กชันใหม่หรือเอกสารที่คล้ายกันตามลําดับตัวอักษรเพื่อให้Cloud Firestoreมีเวลาเพียงพอในการเตรียมเอกสารสําหรับการเข้าชมที่เพิ่มขึ้น เราขอแนะนำให้เริ่มด้วยการดำเนินการสูงสุด 500 ครั้งต่อวินาทีในคอลเล็กชันใหม่ จากนั้นจึงเพิ่มการเข้าชม 50% ทุก 5 นาที คุณเพิ่มปริมาณการเขียนได้เช่นกัน แต่อย่าลืมคำนึงถึงขีดจํากัดมาตรฐานของ Cloud Firestore ตรวจสอบว่าการดำเนินการกระจายอย่างสม่ำเสมอตลอดช่วงของคีย์ ซึ่งเรียกว่ากฎ "500/50/5"

การย้ายข้อมูลการเข้าชมไปยังคอลเล็กชันใหม่

การค่อยๆ เพิ่มปริมาณการเข้าชมมีความสำคัญอย่างยิ่งหากคุณย้ายข้อมูลการเข้าชมแอปจากคอลเล็กชันหนึ่งไปยังอีกคอลเล็กชันหนึ่ง วิธีง่ายๆ ในการจัดการกับการย้ายข้อมูลนี้คือให้อ่านจากคอลเล็กชันเก่า และหากไม่มีเอกสาร ให้อ่านจากคอลเล็กชันใหม่ อย่างไรก็ตาม การดำเนินการนี้อาจทำให้การเข้าชมเอกสารที่คล้ายกันตามลําดับตัวอักษรในคอลเล็กชันใหม่เพิ่มขึ้นอย่างฉับพลัน Cloud Firestore อาจเตรียมคอลเล็กชันใหม่ให้พร้อมรับการเข้าชมที่เพิ่มขึ้นได้อย่างมีประสิทธิภาพ โดยเฉพาะเมื่อคอลเล็กชันมีเอกสารเพียงไม่กี่รายการ

ปัญหาที่คล้ายกันอาจเกิดขึ้นหากคุณเปลี่ยนรหัสเอกสารของเอกสารหลายรายการในคอลเล็กชันเดียวกัน

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

การอ่านแบบขนาน

หากต้องการใช้การอ่านแบบขนานขณะย้ายข้อมูลการเข้าชมไปยังคอลเล็กชันใหม่ ให้อ่านจากคอลเล็กชันเก่าก่อน หากไม่มีเอกสาร ให้อ่านจากคอลเล็กชันใหม่ อัตราการอ่านเอกสารที่ไม่มีอยู่สูงอาจทําให้เกิดจุดที่มีปัญหา ดังนั้นให้ค่อยๆ เพิ่มการโหลดไปยังคอลเล็กชันใหม่ กลยุทธ์ที่ดีกว่าคือคัดลอกเอกสารเก่าไปยังคอลเล็กชันใหม่ แล้วลบเอกสารเก่า เพิ่มการอ่านแบบขนานทีละน้อยเพื่อให้มั่นใจว่า Cloud Firestore จะรองรับการเข้าชมคอลเล็กชันใหม่ได้

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

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

การปรับปรุงกลยุทธ์นี้คือการย้ายข้อมูลผู้ใช้ทีละกลุ่มเล็กๆ เพิ่มช่องในเอกสารผู้ใช้ซึ่งติดตามสถานะการย้ายข้อมูลของผู้ใช้รายนั้น เลือกกลุ่มผู้ใช้ที่จะย้ายข้อมูลตามแฮชของรหัสผู้ใช้ ใช้งานแบบกลุ่มเพื่อย้ายข้อมูลเอกสารของผู้ใช้กลุ่มนั้น และใช้การอ่านแบบขนานสําหรับผู้ใช้ที่อยู่ระหว่างการย้ายข้อมูล

โปรดทราบว่าคุณจะย้อนกลับได้ยาก เว้นแต่คุณจะเขียนทั้งเอนทิตีเก่าและเอนทิตีใหม่พร้อมกันในช่วงการย้ายข้อมูล ซึ่งจะเพิ่มค่าใช้จ่ายCloud Firestore

ความเป็นส่วนตัว

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

ป้องกันการเข้าถึงที่ไม่ได้รับอนุญาต

ป้องกันการดำเนินการที่ไม่ได้รับอนุญาตในฐานข้อมูลด้วย Cloud Firestore Security Rules เช่น การใช้กฎอาจช่วยป้องกันไม่ให้ผู้ใช้ที่เป็นอันตรายดาวน์โหลดฐานข้อมูลทั้งหมดของคุณซ้ำๆ

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Cloud Firestore Security Rules