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

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

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

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

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

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

รหัสเอกสาร

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

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

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

ชื่อช่อง

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

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

ดัชนี

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

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

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

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

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

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

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

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

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

ช่อง TTL

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

ช่องอาร์เรย์หรือช่องแมปขนาดใหญ่

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

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

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

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

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

การลองทำธุรกรรมซ้ำ

SDK และไลบรารีไคลเอ็นต์ใน Cloud Firestore จะลองดำเนินธุรกรรมที่ไม่สำเร็จอีกครั้งโดยอัตโนมัติเพื่อจัดการกับข้อผิดพลาดชั่วคราว หากแอปพลิเคชันเข้าถึง 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 เช่น การใช้กฎอาจหลีกเลี่ยงสถานการณ์ที่ผู้ใช้ที่เป็นอันตรายดาวน์โหลดฐานข้อมูลทั้งหมดซ้ำๆ

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้กฎความปลอดภัยของ Cloud Firestore