מסמך מכיל מערך שיכול לגדול ללא הגבלה עם הזמן, מה שמסכן את מגבלת גודל המסמך של 2 MB (לדוגמה, יומני אירועים, תגובות).
פצל את המערך על פני מספר מסמכי "bucket". כאשר bucket מגיע לסף גודל/פריטים, צור חדש.
למה: שומר על גודל מסמכים בודדים כניתן לניהול תוך שמירה על הקיבוץ הלוגי של נתונים קשורים.
מידול יחס רבים-לרבים (many-to-many), כגון סטודנטים וקורסים, או מאמרים ותגיות.
עבור יחסים מוגבלים, שכפל נתוני יחס בשני הצדדים (לדוגמה, הטמע מזהי קורסים במסמך סטודנט, מזהי סטודנטים במסמך קורס). עבור יחסים בלתי מוגבלים, השתמש ב-container נפרד של "join" או "edge" document.
למה: Denormalization ממטבת עבור שני כיווני השאילתה (סטודנטים בקורס, קורסים לסטודנט) ללא צורך ב-joins. container של join מיועד למקרים בלתי מוגבלים.
מידול נתונים היררכיים (לדוגמה, תרשים ארגוני, קטגוריות מוצרים) וצורך לשאול עבור כל הצאצאים של צומת.
אחסן מערך של כל מזהי האבות או שמותיהם (הנתיב) בכל מסמך.
למה: מאפשר שאילתות תת-עץ יעילות עם מסנן `ARRAY_CONTAINS` יחיד, ומונע בדיקות רקורסיביות יקרות.
למסמך יש מערך בלתי מוגבל (לדוגמה, תגובות בבלוג), אך השאילתה הנפוצה ביותר זקוקה רק לפריטי N האחרונים.
הטמע תת-קבוצה של פריטים אחרונים במסמך הראשי ואחסן את כל הפריטים כמסמכים נפרדים המופנים.
למה: ממטב את נתיב הקריאה הראשי עבור ביצועים ועלות, תוך מתן אפשרות גישה למערך הנתונים המלא בעת הצורך.
אחסון רצף של אירועים בלתי ניתנים לשינוי עבור ישות וצורך לשאול עבור מצב נוכחי או צבירים אנליטיים.
אחסן אירועים ב-container יחיד המחולק לפי מזהה הישות. השתמש ב-Change Feed או Synapse Link כדי לחשב ולאחסן views ממוטבים (materialized views) או צבירים.
למה: מספק תיעוד ביקורת מלא ומפריד את מודל הכתיבה ממודלי קריאה שונים, ומציע גמישות גבוהה.
יש צורך לשמר את מצב הנתונים הקשורים בנקודת זמן ספציפית (לדוגמה, כתובת לקוח בהזמנה).
הטמע עותק (snapshot) של הנתונים הקשורים במסמך, במקום להפנות אליו.
למה: מבטיח דיוק היסטורי על ידי הפרדת המסמך משינויים עתידיים בנתונים המופנים.
קליטת נתוני סדרות זמן בתדירות גבוהה (לדוגמה, קריאות חיישני IoT) וביצוע שאילתות לפי מכשיר על פני טווחי זמן.
השתמש ב-ID של המכשיר כמפתח המחיצה. צבר קריאות למסמכים מחולקי זמן (לדוגמה, שעתיים או דקות) במקום מסמך אחד לכל קריאה.
למה: מפחית באופן דרמטי את ספירת המסמכים ואת RU הכתיבה, תוך מיקום משותף של נתונים עבור שאילתות טווח זמן יעילות בתוך מחיצה.
יש צורך לבצע מספר פעולות יצירה, עדכון או מחיקה כטרנזקציה אטומית יחידה.
השתמש בתכונת TransactionalBatch של ה-SDK. כל הפעולות חייבות להיות ממוקדות לאותו מפתח מחיצה לוגי.
למה: מספק הבטחות ACID עבור עד 100 פעולות בתוך מחיצה אחת, ומבטיח שכל הפעולות מצליחות או שכולן נכשלות יחד.
מסמכים צריכים להימחק אוטומטית מ-container לאחר תקופה מסוימת (לדוגמה, 30 יום).
הפעל Time to Live (TTL) ב-container והגדר את ערך ה-`ttl` ברירת המחדל בשניות (לדוגמה, 2592000 ל-30 יום). `ttl` של -1 במסמך בודד עוקף את ברירת המחדל ומונע פקיעת תוקף.
למה: TTL הוא תכונה ללא עלות המשתמשת ב-RUs עודפים לביצוע מחיקות רקע, ומספקת דרך יעילה וללא מגע אדם לניהול מחזור חיי נתונים.
יש צורך לאחסן אובייקטים בינאריים גדולים (תמונות, סרטונים, מסמכים > 2 MB) המשויכים למטא-דאטה של Cosmos DB.
אחסן את האובייקט הבינארי ב-Azure Blob Storage. אחסן את ה-URI ל-blob במסמך Cosmos DB יחד עם המטא-דאטה.
למה: Cosmos DB ממוטב עבור מטא-דאטה מובנה ובעל מגבלת מסמך של 2 MB. Blob Storage הוא שירות חסכוני וסקאלבילי לאחסון אובייקטים גדולים.
שלב פתרון Azure Cosmos DB
יש צורך לשאול את אותם הנתונים לפי מאפיינים שונים, מה שמוביל לשאילתות cross-partition לא יעילות (לדוגמה, שאילתת הזמנות לפי לקוח, ואז לפי מוצר).
השתמש ב-Change Feed כדי לאכלס container שני (view ממוטב - materialized view) עם אותם הנתונים, אך מחולק לפי מאפיין השאילתה המשני.
למה: מעביר את החישוב מזמן קריאה לזמן כתיבה, ומאפשר שאילתות יעילות של מחיצה בודדת עבור דפוסי גישה מרובים.
יש צורך להריץ שאילתות אנליטיות מורכבות (אגרגציות, joins) על נתונים תפעוליים חיים מבלי להשפיע על עומס העבודה הטרנזקציוני.
הפעל את Azure Synapse Link ב-container של Cosmos DB. הרץ שאילתות אנליטיות מול ה-analytical store של ה-container באמצעות Synapse serverless SQL או Spark pools.
למה: מספק פתרון HTAP ללא ETL, מבוסס ענן. שאילתות מול ה-analytical store העמודתי אינן צורכות RUs טרנזקציוניים והן בעלות ביצועים גבוהים.
יש צורך להפעיל פעולות downstream בצורה סקלאבילית, אמינה וללא שרת (serverless) בתגובה לשינויים בנתונים.
השתמש ב-Azure Function עם ה-Cosmos DB trigger. ה-trigger מנצל את ספריית Change Feed Processor באופן אוטומטי.
למה: זוהי התבנית המומלצת עבור ארכיטקטורות מונעות אירועים. היא מספקת קנה מידה אוטומטי, checkpointing וניהול חכירה של מחיצות.
ערך מפתח מחיצה יחיד מקבל נפח בקשות גבוה באופן לא פרופורציונלי, מה שגורם ל-throttling (מחיצה "חמה").
צור מפתח מחיצה סינתטי על ידי שרשור המפתח המקורי עם סיומת אקראית או מאפיין אחר בעל cardinality גבוה (לדוגמה, `userId + "-" + random(1-10)`).
למה: מפזר את עומס הכתיבה והקריאה עבור ישות לוגית יחידה על פני מספר מחיצות פיזיות, ובכך מקל על throttling.
יש צורך לחלק נתונים לפי מספר רמות (לדוגמה, tenant, ואז שנה, ואז חודש) כדי למנוע מחיצות גדולות ולתמוך בשאילתות מרובות רמות.
הגדר מפתח מחיצה היררכי עם מערך מסודר של נתיבים, כגון `["/tenantId", "/year"]`.
למה: מאפשר תת-חלוקה למחיצות כדי למנוע את מגבלת המחיצה הלוגית של 20 GB ומאפשר ניתוב יעיל יותר עבור שאילתות המסננות לפי ההיררכיה.
יישום מבוזר גלובלית עם multi-region writes מופעל צריך לטפל בעדכונים מקבילים לאותו מסמך.
עבור overwrites פשוטים, השתמש ב-Last-Writer-Wins (LWW). עבור פעולות הדורשות לוגיקת מיזוג (לדוגמה, הגדלת מונה, עדכון מלאי), השתמש במדיניות רזולוציית קונפליקטים מותאמת אישית עם stored procedure של מיזוג.
למה: לוגיקת מיזוג מותאמת אישית מונעת אובדן נתונים (לדוגמה, הגדלה שאבדה) שהיה מתרחש עם LWW, ומבטיחה שלמות נתונים עבור פעולות עסקיות קריטיות.
איזון בין חביון קריאה, זמינות ועקביות נתונים עבור יישום מבוזר גלובלית.
בברירת מחדל, השתמש ב-Session consistency לאיזון טוב ו-read-your-own-writes. השתמש ב-Bounded Staleness עבור lag קריאה צפוי. בטל הגדרה עבור פעולות כתיבה/קריאה קריטיות ספציפיות ל-Strong consistency לפי הצורך.
למה: Session היא הרמה הנפוצה ביותר, המספקת חביון נמוך והבטחות חזקות בתוך session של לקוח. ביטול הגדרה על בסיס בקשה מאפשר גמישות.
מטב פתרון Azure Cosmos DB
פעולות כתיבה צורכות RUs מוגזמים, ורק תת-קבוצה קטנה של מאפייני מסמכים משמשת במסנני שאילתות.
החלף ממדיניות האינדוקס המוגדרת כברירת מחדל למדיניות מותאמת אישית. כלול במפורש נתיבים עבור מאפיינים שנשאלו ושלול את כל שאר הנתיבים (`"/*"` ב-`excludedPaths`).
למה: כל מאפיין מאונדקס כרוך בעלות RU על כתיבות. הכללת מאפיינים שאינם בשימוש יכולה להפחית באופן משמעותי את צריכת RU הכתיבה ואת גודל אחסון האינדקס.
שאילתה תדירה מסננת לפי מאפיין אחד וממיינת לפי אחר (לדוגמה, `WHERE c.status = "active" ORDER BY c.timestamp DESC`).
צור אינדקס מורכב על המאפיינים בסדר הופעתם בשאילתה: `(status ASC, timestamp DESC)` .
למה: מאפשר למנוע השאילתות להגיש את התוצאה המסוננת והממוינת ישירות מהאינדקס, תוך הימנעות מפעולת מיון יקרה בזיכרון והפחתה דרסטית של חיוב ה-RU.
שאילתה מאחזרת מסמכים גדולים אך היישום זקוק רק למאפיין אחד או שניים קטנים מהם.
השתמש ב-query projection כדי לבחור רק את המאפיינים הנדרשים (לדוגמה, `SELECT c.id, c.name FROM c`) במקום `SELECT *`.
למה: מפחית את עלות ה-RU על ידי הפחתת גודל ה-payload של הנתונים המועברים ממנוע מסד הנתונים ללקוח.
יישום שואל לעיתים קרובות עבור עדכוני מסמכים, אך הנתונים משתנים לעיתים רחוקות, מה שמוביל לעלויות RU גבוהות עבור קריאות.
אחסן את ה-ETag מהקריאה האחרונה. בקריאות עוקבות, שלח את ה-ETag בכותרת `If-None-Match`.
למה: אם המסמך לא השתנה, Cosmos DB מחזיר סטטוס 304 Not Modified עם חיוב RU מינימלי (בדרך כלל ~1 RU), ובכך חוסך עלויות ורוחב פס.
ל-workload יש דפוסי תעבורה משתנים או בלתי צפויים, עם שיאים ושפל משמעותיים.
הגדר throughput של autoscale במסד הנתונים או ב-container. הגדר את מקסימום ה-RU/s הנדרשים לעומס שיא.
למה: מגדיל אוטומטית את ה-throughput בין 10% מהמקסימום ועד למקסימום RU/s בהתבסס על השימוש, וממטב עלויות על ידי אי תשלום עבור קיבולת מוקצית שאינה בשימוש.
workload מיועד לפיתוח, בדיקה, או ליישום עם תעבורה נמוכה ותקופות סרק ארוכות.
השתמש במצב קיבולת Serverless עבור חשבון Cosmos DB.
למה: אתה משלם רק עבור RUs הנצרכים לכל פעולה, ללא קיבולת מינימלית מוקצית. זוהי האפשרות החסכונית ביותר עבור workloads ספורדיים.
יש צורך לקלוט או לשנות מספר רב של מסמכים (אלפים עד מיליונים) במהירות האפשרית.
השתמש בתכונת התמיכה ב-bulk של ה-SDK (לדוגמה, `AllowBulkExecution = true` ב-SDK .NET v3).
למה: ה-SDK ממטב עבור throughput גבוה על ידי אצירת פעולות, ניהול מקביליות וטיפול בניסיונות חוזרים/throttling באופן פנימי, ועושה זאת טוב בהרבה מפעולות עוקבות.
stored procedure המעבד אצווה גדולה של מסמכים חורג מזמן.
יישם ביצוע מוגבל. ה-stored procedure צריך לבדוק אם הוא מתקרב למגבלת הביצוע של 5 שניות, ואם כן, להחזיר token המשך ללקוח. הלקוח אז מפעיל מחדש את הפרוצדורה עם ה-token כדי להמשיך בעיבוד.
למה: ל-stored procedures יש מגבלת זמן ביצוע קשיחה. תבנית המשך היא הדרך הסטנדרטית לטיפול בלוגיקה בצד השרת ארוכת טווח ורב-שלבית.
תחזק פתרון Azure Cosmos DB
יישום קריטי לעסק דורש זמינות גבוהה עם אובדן נתונים מינימלי (RPO) וזמן שחזור מהיר (RTO) במקרה של השבתה אזורית.
הגדר את חשבון Cosmos DB עם אזורי כתיבה מרובים והפעל failover אוטומטי.
למה: מספק את ה-RPO וה-RTO הנמוכים ביותר. נתונים משוכפלים על פני אזורים, ובמקרה של השבתה, Cosmos DB מקדם אוטומטית אזור משני להיות אזור הכתיבה הראשי החדש.
יש צורך ביכולת לשחזר ממחיקה או השחתת נתונים מקרית על ידי שחזור מסד הנתונים לנקודת זמן ספציפית.
הפעל את מצב גיבוי רציף (Continuous Backup) בחשבון Cosmos DB.
למה: גיבוי רציף מאפשר לשחזר לכל נקודת זמן (עד לשנייה) בתוך תקופת השמירה (7 או 30 ימים). פעולת השחזור יוצרת חשבון חדש.
דרישת תאימות מחייבת שמפתחות הצפנת נתונים ינוהלו ויישלטו על ידי הלקוח.
הגדר את חשבון Cosmos DB עם מפתחות מנוהלים על ידי הלקוח (CMK), באמצעות מפתח מ-Azure Key Vault.
למה: מספק שכבת אבטחה נוספת שבה אתה שולט במחזור חיי המפתח (כולל סיבוב וביטול) עבור הצפנה במנוחה (encryption-at-rest).
יש צורך להעניק ליישום או למשתמש גישה מבוססת זהות, מדויקת לנתונים, בהתאם לעיקרון ההרשאה המינימלית (least privilege).
השתמש בשילוב Azure AD והקצה תפקיד מובנה (לדוגמה, Cosmos DB Built-in Data Reader) או תפקיד RBAC מותאם אישית, המוגבל ל-container או למסד הנתונים הספציפי.
למה: מבטל את הצורך לנהל ולשתף מפתחות ראשיים. RBAC מספק בקרת גישה מבוססת זהות וניתנת לביקורת.
חשבון Cosmos DB חייב להיות נגיש רק מתוך Azure Virtual Network (VNet) ספציפית, ללא תעבורה דרך האינטרנט הציבורי.
צור Private Endpoint עבור חשבון Cosmos DB ב-VNet ובטל גישת רשת ציבורית בהגדרות ה-firewall.
למה: Private Endpoints מספקים כתובת IP פרטית עבור חשבון Cosmos DB בתוך ה-VNet שלך, ומבטיחים שכל התעבורה זורמת דרך עמוד השדרה המאובטח של Azure.
אבחון שורש הגורם לשגיאות throttling מסוג HTTP 429 (Too Many Requests).
עקוב אחר המדד "Normalized RU Consumption" ב-Azure Monitor. השתמש ב-Diagnostic Logs (`CDBPartitionKeyRUConsumption`) כדי לזהות אילו מפתחות מחיצה צורכים את מירב ה-RUs.
למה: צריכת RU מנורמלת מראה אם ה-throughput הכולל מוצה. יומנים ברמת המחיצה מצביעים על מחיצות חמות, שהן גורם שכיח ל-throttling גם כאשר השימוש הכולל נמוך.
יש צורך לנטר ולהתריע על חביון בקשות כדי להבטיח עמידה ב-SLA.
עקוב אחר המדד "Server Side Latency P99" ב-Azure Monitor. צור כלל התראה עבור מתי מדד זה חורג מסף ה-SLA.
למה: חביון P99 מייצג את חווית המקרה הגרוע ביותר עבור 99% מהבקשות וזה הבסיס ל-SLAs של Cosmos DB. זהו אינדיקטור משמעותי יותר לבעיות ביצועים מאשר חביון ממוצע.
דרישת תאימות קובעת כי כל פעולות גישת הנתונים (קריאות, כתיבות, שאילתות) חייבות לעבור ביקורת.
הפעל הגדרות אבחון (Diagnostic Settings) בחשבון Cosmos DB והעבר את קטגוריית היומן `DataPlaneRequests` ל-Log Analytics workspace או Storage Account.
למה: יומן ה-`DataPlaneRequests` מספק מידע מפורט על כל פעולת נתונים, כולל סוג הפעולה, כתובת IP של הלקוח והמשאב שאליו בוצעה גישה, וזה חיוני לביקורת אבטחה.
לקוח לא מהימן (לדוגמה, אפליקציה לנייד) זקוק לגישה זמנית, מוגבלת, למשאבי Cosmos DB ספציפיים (לדוגמה, רק מסמכים במחיצה שלו).
יישם שירות שכבת ביניים מהימן המאמת את המשתמש, ואז משתמש במפתח ראשי כדי ליצור ולהחזיר token משאב קצר-חיים, מוגבל הרשאות, ללקוח.
למה: זוהי התבנית המאובטחת ביותר לגישה מצד הלקוח, שכן היא מונעת חשיפת מפתחות ראשיים ומספקת בקרת גישה זמנית ומדויקת.