Modelování a dělení dat ve službě Azure Cosmos DB s využitím příkladu z reálného světa
PLATÍ PRO:
SQL API
Tento článek vychází z několika konceptů Azure Cosmos DB,jako je modelování dat,dělení a zřízená propustnost, a ukazuje, jak řešit reálné cvičení návrhu dat.
Pokud obvykle pracujete s relačními databázemi, pravděpodobně jste vytyčovat zvyklosti a intuici týkající se návrhu datového modelu. Vzhledem ke konkrétním omezením, ale také jedinečným přednostem Azure Cosmos DB, se většina těchto osvědčených postupů nevyhodnotí dobře a může vás přetáhnout do neoptimálních řešení. Cílem tohoto článku je provést vás kompletním procesem modelování reálného případu použití v Azure Cosmos DB, od modelování položek po kolokaci entit a dělení kontejnerů.
Stáhněte si nebo zobrazte zdrojový kód vygenerovaný komunitou, který ilustruje koncepty z tohoto článku. Tento vzorový kód přispěl přispěvatel komunity a tým Azure Cosmos DB nepodporuje jeho údržbu.
Scénář
V tomto cvičení se budeme zabývat doménou platformy pro blogování, kde uživatelé mohou vytvářet příspěvky. Uživatelé mohou také tyto příspěvky rádi a přidávat do nich komentáře.
Tip
Některá slova jsme zvýrazňli kurzívou; Tato slova identifikují druh "věcí", se které bude náš model muset manipulovat.
Přidání dalších požadavků do specifikace:
- Na přední stránce se zobrazí informační kanál nedávno vytvořených příspěvků.
- Můžeme načíst všechny příspěvky pro uživatele, všechny komentáře k příspěvku a všechny lajky pro příspěvek.
- Příspěvky se vrátí s uživatelským jménem jejich autorů a spočítá se, kolik komentářů a lajků mají.
- Komentáře a lajky se také vrátí s uživatelským jménem uživatelů, kteří je vytvořili.
- Při zobrazení jako seznamy musí příspěvky prezentovat pouze zkrácený souhrn jejich obsahu.
Identifikace hlavních vzorů přístupu
Začneme tím, že identifikujeme vzory přístupu našeho řešení a poskytneme počáteční specifikaci určité struktury. Při navrhování datového modelu pro Azure Cosmos DB je důležité pochopit, které požadavky bude náš model muset obsluhovat, aby se ujistil, že model bude tyto požadavky obsluhovat efektivně.
Aby byl celkový proces jednodušší, kategorizizujeme tyto různé požadavky jako příkazy nebo dotazy a vypůjčíme si nějakou slovní zásobu z CQRS, kde příkazy jsou požadavky na zápis (to znamená záměry k aktualizaci systému) a dotazy jsou požadavky jen pro čtení.
Tady je seznam požadavků, které naše platforma bude muset zveřejnit:
- [C1] Vytvoření nebo úprava uživatele
- [Otázka č. 1] Načtení uživatele
- [C2] Vytvoření nebo úprava příspěvku
- [Otázka č. 2] Načtení příspěvku
- [Otázka č. 3] Zobrazení seznamu příspěvků uživatele ve krátkém tvaru
- [C3] Vytvoření komentáře
- [Otázka č. 4] Zobrazení seznamu komentářů k příspěvku
- [C4] Like a post
- [Q5] Seznam lajků příspěvku
- [Otázka č. 6] Vypište x nejnovějších příspěvků vytvořených ve krátkém tvaru (informační kanál).
V této fázi jsme nemysle na podrobnosti o tom, co každá entita (uživatel, příspěvek atd.) bude obsahovat. Tento krok je obvykle jedním z prvních kroků, které je třeba řešit při navrhování s relačním úložištěm, protože musíme zjistit, jak se tyto entity přeloží z hlediska tabulek, sloupců, cizích klíčů atd. Databáze dokumentů, která při zápisu nevynucuje žádné schéma, je mnohem méně důležité.
Hlavním důvodem, proč je důležité identifikovat vzory přístupu od začátku, je to, že tento seznam požadavků bude naší testovací sadu. Pokaždé, když budeme iterovat datovým modelem, si projdeme všechny požadavky a zkontrolujeme jeho výkon a škálovatelnost. Vypočítáme jednotky žádostí spotřebované v jednotlivých modelech a optimalizujeme je. Všechny tyto modely používají výchozí zásady indexování a můžete je přepsat indexováním konkrétních vlastností, což může dále zlepšit spotřebu RU a latenci.
V1: První verze
Začneme se dvěma kontejnery: a users posts .
Kontejner Users
V tomto kontejneru jsou uloženy pouze položky uživatelů:
{
"id": "<user-id>",
"username": "<username>"
}
Tento kontejner rozdělíme podle , což znamená, že každý logický oddíl v tomto kontejneru id bude obsahovat jenom jednu položku.
Kontejner Posts
Tento kontejner hostuje příspěvky, komentáře a lajky:
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"title": "<post-title>",
"content": "<post-content>",
"creationDate": "<post-creation-date>"
}
{
"id": "<comment-id>",
"type": "comment",
"postId": "<post-id>",
"userId": "<comment-author-id>",
"content": "<comment-content>",
"creationDate": "<comment-creation-date>"
}
{
"id": "<like-id>",
"type": "like",
"postId": "<post-id>",
"userId": "<liker-id>",
"creationDate": "<like-creation-date>"
}
Tento kontejner rozdělíme podle , což znamená, že každý logický oddíl v tomto kontejneru bude obsahovat jeden příspěvek, všechny komentáře pro tento příspěvek a všechny postId lajky pro tento příspěvek.
Všimněte si, že jsme do položek uložených v tomto kontejneru zavedli vlastnost, která rozlišuje mezi třemi typy entit, které type tento kontejner hostuje.
Také jsme se rozhodli odkazovat na související data místo jejich vkládání (podrobnosti o těchto konceptech najdete v této části), protože:
- neexistuje žádné horní omezení počtu příspěvků, které může uživatel vytvořit.
- příspěvky mohou být libovolně dlouhé,
- neexistuje žádné horní omezení počtu komentářů a lajků, které může příspěvek mít,
- Chceme mít možnost přidat komentář nebo něco jako do příspěvku, aniž bychom museli aktualizovat samotný příspěvek.
Jak dobře náš model funguje?
Teď je čas posoudit výkon a škálovatelnost naší první verze. U každého z dříve identifikovaných požadavků měříme její latenci a počet jednotek žádostí, které spotřebovává. Toto měření se provádí u fiktivní datové sady obsahující 100 000 uživatelů s 5 až 50 příspěvky na uživatele a až 25 komentářů a 100 lajků na příspěvek.
[C1] Vytvoření nebo úprava uživatele
Tento požadavek se snadno implementuje, protože jednoduše vytvoříme nebo aktualizujeme položku v users kontejneru. Požadavky se díky klíči oddílu dobře rozprostře mezi id všechny oddíly.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 7 ms | 5,71 RU | ✅ |
[Otázka č. 1] Načtení uživatele
Načtení uživatele se provádí přečtením odpovídající položky z users kontejneru.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 2 ms | 1 RU | ✅ |
[C2] Vytvoření nebo úprava příspěvku
Podobně jako u [C1] stačí zapisovat do posts kontejneru.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 9 ms | 8,76 RU | ✅ |
[Otázka č. 2] Načtení příspěvku
Začneme načtením odpovídajícího dokumentu z posts kontejneru. To ale nestačí, podle naší specifikace musíme také agregovat uživatelské jméno autora příspěvku a počty komentářů a lajků, které tento příspěvek má, což vyžaduje, aby byly vydány 3 SQL dotazy.
Každý z dalších dotazů filtruje klíč oddílu příslušného kontejneru, což je přesně to, co chceme maximalizovat výkon a škálovatelnost. Nakonec ale musíme provést čtyři operace, abychom vrátili jeden příspěvek, takže to v další iteraci vylepšíme.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 9 ms | 19,54 RU | ⚠ |
[Otázka č. 3] Zobrazení seznamu příspěvků uživatele ve krátkém tvaru
Nejprve musíme načíst požadované příspěvky pomocí SQL, který načte příspěvky odpovídající konkrétnímu uživateli. Musíme ale také zadat další dotazy, které agregují uživatelské jméno autora a počty komentářů a lajků.
Tato implementace má mnoho nevýhod:
- Dotazy agregující počty komentářů a lajků se musí vydávat pro každý příspěvek vrácený prvním dotazem.
- Hlavní dotaz nefiltruje klíč oddílu kontejneru, což vede k rozdělení a prohledávání oddílů
postsv rámci kontejneru.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 130 ms | 619,41 RU | ⚠ |
[C3] Vytvoření komentáře
Komentář se vytvoří zápisem odpovídající položky v posts kontejneru.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 7 ms | 8,57 RU | ✅ |
[Otázka č. 4] Zobrazení seznamu komentářů k příspěvku
Začneme dotazem, který načte všechny komentáře pro tento příspěvek, a znovu musíme agregovat uživatelská jména zvlášť pro každý komentář.
I když hlavní dotaz filtruje klíč oddílu kontejneru, agregace uživatelských jmen samostatně penalizuje celkový výkon. Později to vylepšíme.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 23 ms | 27,72 RU | ⚠ |
[C4] Like a post
Stejně jako [C3] vytvoříme odpovídající položku v posts kontejneru.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 6 ms | 7,05 RU | ✅ |
[Q5] Seznam lajků příspěvku
Stejně jako v [Q4] se na tento příspěvek dotazuje lajků a pak agreguje jejich uživatelská jména.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 59 ms | 58,92 RU | ⚠ |
[Otázka č. 6] Vypište x nejnovějších příspěvků vytvořených ve krátkém tvaru (informační kanál).
Nejnovější příspěvky načteme dotazem na kontejner seřazený podle data sestupného vytvoření a pak agregací uživatelských jmen a počtů komentářů a lajků pro každý posts z těchto příspěvků.
Náš počáteční dotaz znovu nefiltruje klíč oddílu kontejneru, což aktivuje posts nákladný plán. To je ještě horší, protože cílíme na mnohem větší sadu výsledků a výsledky seřadíme pomocí klauzule , což z hlediska jednotek ORDER BY žádostí zvětšuje jeho náklad.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 306 ms | 2063,54 RU | ⚠ |
Promítání výkonu V1
Při pohledu na problémy s výkonem, se kterým jsme se setkali v předchozí části, můžeme identifikovat dvě hlavní třídy problémů:
- Některé požadavky vyžadují, aby bylo možné shromáždit všechna data, která potřebujeme vrátit, více dotazů.
- Některé dotazy nefiltruje klíč oddílu kontejnerů, na které cílí, což vede k rozdělení, které brání škálovatelnosti.
Pojďme každý z těchto problémů vyřešit. Začneme prvním z nich.
V2: Představení denormalizace pro optimalizaci dotazů pro čtení
Důvodem, proč v některých případech musíme vydávat další požadavky, je to, že výsledky počátečního požadavku neobsahují všechna data, která potřebujeme vrátit. Při práci s nerelačním úložištěm dat, jako je Azure Cosmos DB, se tento typ problému obvykle řeší denormalizací dat v rámci naší datové sady.
V našem příkladu upravíme položky post tak, aby se přidalo uživatelské jméno autora příspěvku, počet komentářů a počet lajků:
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"userUsername": "<post-author-username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <count-of-comments>,
"likeCount": <count-of-likes>,
"creationDate": "<post-creation-date>"
}
Upravíme také komentáře a podobně jako položky a přidáme uživatelské jméno uživatele, který je vytvořil:
{
"id": "<comment-id>",
"type": "comment",
"postId": "<post-id>",
"userId": "<comment-author-id>",
"userUsername": "<comment-author-username>",
"content": "<comment-content>",
"creationDate": "<comment-creation-date>"
}
{
"id": "<like-id>",
"type": "like",
"postId": "<post-id>",
"userId": "<liker-id>",
"userUsername": "<liker-username>",
"creationDate": "<like-creation-date>"
}
Denormalizace komentářů a like counts
Chceme toho dosáhnout tak, že pokaždé, když přidáme komentář nebo něco takového, zvýšíme také hodnotu nebo v commentCount likeCount odpovídajícím příspěvku. Vzhledem k tomu, že náš kontejner je rozdělený do oddílů , nová položka (komentář nebo podobně) a její odpovídající příspěvek se nachází posts postId ve stejném logickém oddílu. V důsledku toho můžeme k provedení této operace použít uloženou proceduru.
Při vytváření komentáře ([C3] ) teď místo toho, abychom do kontejneru přidali novou položku, nazýváme v tomto kontejneru posts následující uloženou proceduru:
function createComment(postId, comment) {
var collection = getContext().getCollection();
collection.readDocument(
`${collection.getAltLink()}/docs/${postId}`,
function (err, post) {
if (err) throw err;
post.commentCount++;
collection.replaceDocument(
post._self,
post,
function (err) {
if (err) throw err;
comment.postId = postId;
collection.createDocument(
collection.getSelfLink(),
comment
);
}
);
})
}
Tato uložená procedura přebírá JAKO parametry ID příspěvku a text nového komentáře a pak:
- načte příspěvek.
- zvýší hodnotu
commentCount - nahrazuje příspěvek
- přidá nový komentář.
Protože se uložené procedury provádějí jako atomické transakce, hodnota a skutečný počet komentářů zůstanou vždy commentCount synchronizované.
Při přidávání nových lajků ke zvýšení hodnoty samozřejmě nazýváme podobnou uloženou likeCount proceduru.
Denormalizace uživatelských jmen
Uživatelská jména vyžadují jiný přístup, protože uživatelé nejen jsou v různých oddílech, ale i v jiném kontejneru. Když musíme denormalizovat data mezi oddíly a kontejnery, můžeme použít kanál změn zdrojového kontejneru.
V našem příkladu používáme kanál změn kontejneru, který reaguje users vždy, když uživatelé aktualizují svá uživatelská jména. Když k tomu dojde, rozšíříme změnu voláním jiné uložené procedury v posts kontejneru:
function updateUsernames(userId, username) {
var collection = getContext().getCollection();
collection.queryDocuments(
collection.getSelfLink(),
`SELECT * FROM p WHERE p.userId = '${userId}'`,
function (err, results) {
if (err) throw err;
for (var i in results) {
var doc = results[i];
doc.userUsername = username;
collection.upsertDocument(
collection.getSelfLink(),
doc);
}
});
}
Tato uložená procedura jako parametry přebírá ID uživatele a nové uživatelské jméno uživatele a pak:
- načte všechny položky, které odpovídají
userId(což mohou být příspěvky, komentáře nebo lajky). - pro každou z těchto položek
- nahrazuje
userUsername - nahradí položku
- nahrazuje
Důležité
Tato operace je nákladná, protože vyžaduje, aby se tato uložená procedura spouštěna v každém oddílu posts kontejneru. Předpokládáme, že většina uživatelů si během registrace zvolí vhodné uživatelské jméno a nikdy ho nezmění, takže tato aktualizace bude běžet velmi zřídka.
Jaké jsou zvýšení výkonu V2?
[Otázka č. 2] Načtení příspěvku
Když teď máme denormalizaci nastavenou, musíme načíst jenom jednu položku, která požadavek zřídí.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 2 ms | 1 RU | ✅ |
[Otázka č. 4] Zobrazení seznamu komentářů k příspěvku
Opět můžeme ušetřit dodatečné požadavky, které načítaly uživatelská jména, a nakonec použít jeden dotaz, který filtruje klíč oddílu.
| Latence | Poplatky za RU | Výkon |
|---|---|---|
| 4 ms | 7,72 RU | ✅ |
[Q5] Seznam podobných příspěvků
Přesná stejná situace při výpisu podobných.
| Latence | Poplatek za RU | Výkon |
|---|---|---|
| 4 MS | 8,92 RU | ✅ |
V3: zajištění škálovatelnosti všech požadavků
V našich celkových vylepšeních výkonu stále existují dvě požadavky, které jsme nedokončili plně optimalizované: [Q3] a [Q6]. Jedná se o požadavky zahrnující dotazy, které nemají filtr na klíč oddílu kontejnerů, na které cílí.
Q3 Seznam příspěvků uživatele v krátké podobě
Tato žádost už přináší výhody vylepšení zavedených ve verzi v2, která vyprázdní další dotazy.
Ale zbývající dotaz se stále nefiltruje na klíč oddílu posts kontejneru.
Způsob, jak si představit tuto situaci, je ve skutečnosti jednoduchá:
- Tento požadavek musí vyfiltrovat,
userIdprotože chceme načíst všechny příspěvky pro konkrétního uživatele. - Nefunguje dobře, protože se provádí na
postskontejneru, který není rozdělený na oddílyuserId - V takovém případě by byl problém s výkonem vyřešen provedením tohoto požadavku na kontejneru, který je rozdělen do oddílů.
userId - Tím se zapíná, že tento kontejner již máme
users.
Proto zavádíme druhou úroveň denormalizace tím, že duplikujete celé příspěvky do users kontejneru. Díky tomu máme efektivně kopii našich příspěvků, které jsou rozdělené jenom na oddíly v různých dimenzích. díky tomu je jejich využívání efektivnější userId .
usersKontejner teď obsahuje 2 druhy položek:
{
"id": "<user-id>",
"type": "user",
"userId": "<user-id>",
"username": "<username>"
}
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"userUsername": "<post-author-username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <count-of-comments>,
"likeCount": <count-of-likes>,
"creationDate": "<post-creation-date>"
}
Poznámky:
- zavedli jsme do
typepoložky uživatele pole pro odlišení uživatelů od příspěvků. - do položky uživatele jsme také přidali
userIdpole, které je redundantní sidpolem, ale je potřeba, protožeuserskontejner je teď rozdělený na oddílyuserId(a neidjako dříve).
Pro dosažení této denormalizace znovu použijeme kanál změn. Tentokrát reagujeme na kanál změn posts kontejneru, který odesílá nové nebo aktualizované příspěvky do users kontejneru. A vzhledem k tomu, že výpis příspěvků nevyžaduje vrácení celého obsahu, můžeme je v procesu zkrátit.
Nyní můžeme směrovat dotaz do users kontejneru a filtrovat klíč oddílu kontejneru.
| Latence | Poplatek za RU | Výkon |
|---|---|---|
| 4 MS | 6,46 RU | ✅ |
[Q6] Seznam naposledy vytvořených příspěvků v krátké formě (informační kanál)
Budeme se muset vypořádat s podobným případem: i po tom, co povede k odstranění dalších dotazů, které byly nepotřebné denormalizací představené v v2, zbývající dotaz nefiltruje na klíč oddílu kontejneru:
Po stejném přístupu vyžaduje maximalizaci výkonu a škálovatelnosti této žádosti, aby se narazí jenom na jeden oddíl. To je možné, protože potřebujeme vracet jenom omezený počet položek; abychom mohli naplnit domovskou stránku vaší domovské platformy, stačí získat nejnovější příspěvky 100, aniž byste museli stránkovat celou datovou sadu.
Takže pro optimalizaci této poslední žádosti zavádíme třetí kontejner pro náš návrh, který je zcela vyhrazený pro obsluhu této žádosti. Naši příspěvky jsme denormalizují na tento nový feed kontejner:
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"userUsername": "<post-author-username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <count-of-comments>,
"likeCount": <count-of-likes>,
"creationDate": "<post-creation-date>"
}
Tento kontejner je rozdělen do oddílů type , což bude vždy post v našich položkách. Tím se zajistí, že všechny položky v tomto kontejneru budou zasedat do stejného oddílu.
Abychom dosáhli denormalizace, musíme jenom připojit se k kanálu změny kanálu, který jsme předtím zavedli k odeslání příspěvků do tohoto nového kontejneru. Je důležité, abyste měli jistotu, že ukládáme jenom 100 nejnovějších příspěvků. v opačném případě může obsah kontejneru přesáhnout maximální velikost oddílu. To se provádí voláním post-triggeru pokaždé, když se do kontejneru přidá dokument:
Tady je text aktivační události, která tuto kolekci zkrátí:
function truncateFeed() {
const maxDocs = 100;
var context = getContext();
var collection = context.getCollection();
collection.queryDocuments(
collection.getSelfLink(),
"SELECT VALUE COUNT(1) FROM f",
function (err, results) {
if (err) throw err;
processCountResults(results);
});
function processCountResults(results) {
// + 1 because the query didn't count the newly inserted doc
if ((results[0] + 1) > maxDocs) {
var docsToRemove = results[0] + 1 - maxDocs;
collection.queryDocuments(
collection.getSelfLink(),
`SELECT TOP ${docsToRemove} * FROM f ORDER BY f.creationDate`,
function (err, results) {
if (err) throw err;
processDocsToRemove(results, 0);
});
}
}
function processDocsToRemove(results, index) {
var doc = results[index];
if (doc) {
collection.deleteDocument(
doc._self,
function (err) {
if (err) throw err;
processDocsToRemove(results, index + 1);
});
}
}
}
Posledním krokem je přesměrování našeho dotazu na náš nový feed kontejner:
| Latence | Poplatek za RU | Výkon |
|---|---|---|
| 9 MS | 16,97 RU | ✅ |
Závěr
Pojďme se podívat na celkové vylepšení výkonu a škálovatelnosti, které jsme zavedli v různých verzích našeho návrhu.
| V1 | V2 | Technologie | |
|---|---|---|---|
| C1 | 7 MS/5,71 RU | 7 MS/5,71 RU | 7 MS/5,71 RU |
| Dotazu | 2 MS/1 RU | 2 MS/1 RU | 2 MS/1 RU |
| Řidičské | 9 MS/8,76 RU | 9 MS/8,76 RU | 9 MS/8,76 RU |
| F2 | 9 MS/19,54 RU | 2 MS/1 RU | 2 MS/1 RU |
| Q3 | 130 MS/619,41 RU | 28 MS/201,54 RU | 4 MS/6,46 RU |
| C3 | 7 MS/8,57 RU | 7 MS/15,27 RU | 7 MS/15,27 RU |
| Dotaz | 23 MS/27,72 RU | 4 MS/7,72 RU | 4 MS/7,72 RU |
| C4 | 6 MS/7,05 RU | 7 MS/14,67 RU | 7 MS/14,67 RU |
| [Q5] | 59 MS/58,92 RU | 4 MS/8,92 RU | 4 MS/8,92 RU |
| [Q6] | 306 MS/2063,54 RU | 83 MS/532,33 RU | 9 MS/16,97 RU |
Vyoptimalizovali jsme scénář pro čtení a těžký přístup.
Možná jste si všimli, že jsme provedli soustředěné úsilí na zlepšení výkonu žádostí o čtení (dotazů) na úkor požadavků na zápis (příkazy). V mnoha případech teď operace zápisu aktivují následnou denormalizaci prostřednictvím změnových kanálů. díky tomu jsou výpočty mnohem levnější a delší než vyhodnotit.
To je odůvodněné tím, že platforma blogů (podobně jako většina sociálních aplikací) je čitelná, což znamená, že množství požadavků na čtení, které musí zpracovat, je obvykle pořadí, které je vyšší než množství požadavků na zápis. Proto je vhodné zajistit, aby se žádosti o zápis dražší, aby bylo možné zpracovávat žádosti o čtení levnější a lepší výkon.
Pokud se podíváme na nejvíce extrémní optimalizaci, [Q6] se z 2000 + ru na pouhých 17 ru; dosáhli jsme, že denormalizace příspěvků za cenu kolem 10 ru na položku. Vzhledem k tomu, že jsme pomohli spoustu dalších žádostí o informační kanál než vytváření nebo aktualizace příspěvků, jsou náklady na tuto denormalizaci zanedbatelné z hlediska celkové úspory.
Denormalizace se dá použít přírůstkově.
Vylepšení škálovatelnosti, která jsme prozkoumali v tomto článku, zahrnují denormalizaci a duplikaci dat napříč datovou sadou. Je potřeba poznamenat, že tyto optimalizace nemusíte zařadit do 1. dne. Dotazy, které filtrují klíče oddílů, fungují lépe při škálování, ale dotazy napříč oddíly mohou být zcela přijatelné, pokud jsou volány zřídka nebo proti omezené sadě dat. Pokud vytváříte prototyp nebo spouštíte produkt s malou a řízenou uživatelskou základnou, můžete tato vylepšení vylepšit později. důležité je, abyste mohli monitorovat výkon svého modelu, abyste se mohli rozhodnout, jestli a kdy je čas je uvést do.
Kanál změn, který používáme k distribuci aktualizací do jiných kontejnerů, ukládá všechny aktualizace trvale. Díky tomu je možné vyžádat všechny aktualizace od vytvoření kontejneru a spustit Denormalizovaná zobrazení jako jednorázovou operaci zachytávání i v případě, že váš systém již obsahuje velké množství dat.
Další kroky
Po tomto úvodu do modelování praktických a segmentace dat můžete v následujících článcích zkontrolovat koncepty, které jsme pokryli:
- Práce s databázemi, kontejnery a položkami
- Dělení ve službě Azure Cosmos DB
- změnit informační kanál v Azure Cosmos DB
chcete se pokusit plánování kapacity pro migraci na Azure Cosmos DB? Pro plánování kapacity můžete použít informace o vašem existujícím databázovém clusteru.
- Pokud znáte počet virtuální jádra a serverů v existujícím databázovém clusteru, přečtěte si téma odhadování jednotek žádostí pomocí virtuální jádra nebo vCPU .
- pokud znáte typické míry požadavků pro aktuální databázovou úlohu, přečtěte si téma odhadace jednotek žádostí pomocí Azure Cosmos DB kapacity plánovače .