ใช้แนวทางปฏิบัติแนะนำที่แสดงที่นี่เพื่อเป็นข้อมูลอ้างอิงอย่างรวดเร็วเมื่อสร้างแอปพลิเคชันที่ใช้ 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