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: ROZHRANÍ SQL API

Tento článek se sestavuje na několika Azure Cosmos DB konceptech, jako jsou modelování dat, vytváření oddílůa zajištěná propustnost , která ukazují, jak se vypořádat s návrhem dat reálného světa.

Pokud obvykle pracujete s relačními databázemi, pravděpodobně jste vytvořili zvyky a intuitionsi, jak navrhnout datový model. Vzhledem k konkrétním omezením, ale i k jedinečným síluem Azure Cosmos DB se většina těchto osvědčených postupů neprojeví dobře a může vás přetáhnout do podoptimálních řešení. Cílem tohoto článku je projít si kompletní proces modelování reálného případu použití na Azure Cosmos DB, z modelování položek až po společné umístění entit a vytváření oddílů kontejnerů.

Stáhněte si nebo zobrazte zdrojový kód generovaný komunitou , který ilustruje koncepty z tohoto článku. Tento vzorový kód přispěl Přispěvatel komunity a Azure Cosmos DB tým nepodporuje jeho údržbu.

Scénář

Pro toto cvičení bereme v úvahu doménu blogovací platformy, kde můžou Uživatelé vytvářet příspěvky. Uživatelé můžou také jako příspěvky přidávat Komentáře .

Tip

Některá slova byla v kurzívě zvýrazněna. Tato slova identifikují druh "věcí" Náš model bude muset manipulovat.

Přidání dalších požadavků do naší specifikace:

  • Na úvodní stránce se zobrazuje 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, podobně jako u příspěvku,
  • Příspěvky se vrátí s uživatelským jménem svých autorů a počtem, kolik komentářů a jako mají.
  • Komentáře a podobné věci se také vrátí s uživatelským jménem uživatelů, kteří je vytvořili.
  • Při zobrazení jako seznamů musí příspěvky obsahovat jenom zkrácený souhrn jejich obsahu.

Identifikujte hlavní vzory přístupu.

Abychom mohli začít, poskytujeme určitou strukturu pro naši počáteční specifikaci tím, že identifikujeme vzory přístupu našich řešení. Když navrhujete datový model pro Azure Cosmos DB, je důležité pochopit, které požadavky má náš model sloužit k tomu, aby se zajistilo, že model bude tyto požadavky efektivně obsluhovat.

Aby bylo možné celkový postup sledovat, kategorizujte tyto různé požadavky jako příkazy nebo dotazy, přičemž jste si vypůjčili některé slovníky z CQRS , kde příkazy jsou požadavky na zápis (tj. záměry aktualizovat systém) a dotazy jsou požadavky jen pro čtení.

Tady je seznam požadavků, které bude tato platforma muset vystavit:

  • [C1] Vytvořit/upravit uživatele
  • [Q1] Načtení uživatele
  • [C2] Vytvořit nebo upravit příspěvek
  • [Q2] Načtení příspěvku
  • [Q3] Seznam příspěvků uživatele v krátké podobě
  • [C3] Vytvoření komentáře
  • [4. čtvrtletí] Výpis komentáře příspěvku
  • [C4] Jako příspěvek
  • [Q5] Seznam podobných příspěvků
  • [Q6] Seznam naposledy vytvořených příspěvků v krátké formě (informační kanál)

V této fázi jsme si nemysleli, jaké informace o tom, co jednotlivé entity (uživatelé, příspěvky atd.) budou obsahovat. Tento krok je obvykle mezi prvními, aby se provedl při navrhování na relačním úložišti, protože je nutné zjistit, jak budou tyto entity překládat z hlediska tabulek, sloupců, cizích klíčů atd. Je mnohem méně obav s databází dokumentů, která neuplatňuje žádné schéma při zápisu.

Hlavním důvodem, proč je důležité identifikovat naše vzory přístupu od začátku, je to, že tento seznam žádostí bude naší sadou testů. Pokaždé, když procházíme přes náš datový model, projdeme jednotlivé požadavky a zkontrolujeme výkon a škálovatelnost. Vyhodnotí se jednotky žádostí spotřebované v jednotlivých modelech a optimalizuje se. Všechny tyto modely používají výchozí zásady indexování a můžete je přepsat nastavením specifických vlastností, což může dále zlepšit spotřebu RU a latenci.

V1: první verze

Začneme se dvěma kontejnery: users a posts .

Kontejner uživatelů

Tento kontejner ukládá pouze položky uživatele:

{
    "id": "<user-id>",
    "username": "<username>"
}

Tento kontejner nastavíme id na oddíly, což znamená, že každý logický oddíl v tomto kontejneru bude obsahovat jenom jednu položku.

Kontejner příspěvků

Tento kontejner hostuje příspěvky, komentáře a podobné věci:

{
    "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 nastavíme postId na oddíly, což znamená, že každý logický oddíl v tomto kontejneru bude obsahovat jeden příspěvek, všechny komentáře pro daný příspěvek a všechny podobné položky pro daný příspěvek.

Všimněte si, že jsme type v položkách uložených v tomto kontejneru zavedli vlastnost, která rozlišuje tři typy entit, které tento kontejner hostuje.

Také jsme se rozhodli odkázat na související data, aniž byste je vložili (podrobnosti o těchto konceptech najdete v této části ):

  • neexistuje horní limit počtu příspěvků, které může uživatel vytvořit.
  • příspěvky můžou být svévolně dlouhé,
  • není k dispozici horní limit počtu komentářů a podobně jako u příspěvku může být.
  • Chceme být schopni přidat komentář nebo podobně jako příspěvek bez nutnosti aktualizovat příspěvek samotného příspěvku.

Jak to náš model funguje?

Teď je čas vyhodnotit výkon a škálovatelnost naší první verze. Pro všechny dříve identifikované požadavky měříme latenci a počet jednotek požadavků, které spotřebovává. Toto měření se provádí na základě zástupné datové sady obsahující 100 000 uživatelů s 5 až 50 příspěvky na uživatele a až 25 komentářů a 100 jako na příspěvek.

C1 Vytvořit/upravit uživatele

Tuto žádost je jednoduché implementovat, protože právě vytvoříme nebo aktualizujeme položku v users kontejneru. Požadavky budou v rámci všech oddílů v tomto případě bez ohledu na klíč oddílu v tomto případě úhledně rozloženy id .

Zápis jedné položky do kontejneru Users

Latence Poplatek za RU Výkon
7 MS 5,71 RU

Dotazu Načtení uživatele

Načítání uživatele se provádí čtením odpovídající položky z users kontejneru.

Načtení jedné položky z kontejneru uživatelů

Latence Poplatek za RU Výkon
2 MS 1 RU

Řidičské Vytvořit nebo upravit příspěvek

Podobně jako [C1] musíme pouze zapisovat do posts kontejneru.

Zápis jedné položky do kontejneru příspěvky

Latence Poplatek za RU Výkon
9 MS 8,76 RU

F2 Načtení příspěvku

Začneme načtením odpovídajícího dokumentu z posts kontejneru. Ale to není dostatečné, podle našich specifikací také musí být agregované uživatelské jméno autora příspěvku a počty komentářů a kolika má tento příspěvek obsahovat 3 další dotazy SQL, které mají být vydány.

Načtení příspěvku a agregace dalších dat

Každý z dalších dotazů filtruje klíč oddílu příslušného kontejneru, který přesně odpovídá tomu, co chceme maximalizovat výkon a škálovatelnost. Ale nakonec musíme provést čtyři operace, aby vracely jediný příspěvek, takže ho v další iteraci Vylepšete.

Latence Poplatek za RU Výkon
9 MS 19,54 RU

Q3 Seznam příspěvků uživatele v krátké podobě

Nejdřív musíme načíst požadované příspěvky s dotazem SQL, který načte příspěvky odpovídající tomuto konkrétnímu uživateli. Je ale také nutné vystavit další dotazy pro agregaci uživatelského jména autora a počty komentářů a jako je.

Načítání všech příspěvků pro uživatele a agregace jejich dalších dat

Tato implementace představuje mnoho nevýhod:

  • dotazy, které agreguje počty komentářů a jako je třeba vydat pro každý příspěvek vrácený prvním dotazem,
  • hlavní dotaz nefiltruje klíč oddílu posts kontejneru, což vede k vyzkoušení ventilátoru a kontrole oddílů v rámci kontejneru.
Latence Poplatek za RU Výkon
130 MS 619,41 RU

C3 Vytvoření komentáře

Komentář je vytvořen zápisem odpovídající položky do posts kontejneru.

Zápis jedné položky do kontejneru příspěvky

Latence Poplatek za RU Výkon
7 MS 8,57 RU

Dotaz Výpis komentáře příspěvku

Začneme s dotazem, který načte všechny komentáře k tomuto příspěvku a znovu je také potřeba agregovat pro každý komentář samostatně.

Načítání všech komentářů k příspěvku a agregace jejich dalších dat

I když hlavní dotaz filtruje klíč oddílu kontejneru, agreguje uživatelská jména, a to bez ohledu na celkový výkon. Vylepšete ho později.

Latence Poplatek za RU Výkon
23 MS 27,72 RU

C4 Jako příspěvek

Stejně jako [C3] vytvoříme odpovídající položku v posts kontejneru.

Zápis jedné položky do kontejneru příspěvky

Latence Poplatek za RU Výkon
6 MS 7,05 RU

[Q5] Seznam podobných příspěvků

Stejně jako u tohoto příspěvku se jako [Q4] dotazuje jako pro tento příspěvek a pak agreguje svá uživatelská jména.

Načtení všech podobně jako u příspěvku a agregace jejich dalších dat

Latence Poplatek za RU Výkon
59 MS 58,92 RU

[Q6] Seznam naposledy vytvořených příspěvků v krátké formě (informační kanál)

Nejnovější příspěvky načítáme dotazem na posts kontejner seřazený podle data sestupného vytváření a pak agregovaná uživatelská jména a počty komentářů a podobně jako u jednotlivých příspěvků.

Načítání nejnovějších příspěvků a agregace jejich dalších dat

Po opětovném spuštění náš počáteční dotaz nefiltruje klíč oddílu posts kontejneru, který aktivuje nákladný ventilátor. Tato jedna je ještě horší, protože cílíme na mnohem větší sadu výsledků a seřadíme výsledky s ORDER BY klauzulí, což snižuje náklady na jednotky požadavků.

Latence Poplatek za RU Výkon
306 MS 2063,54 RU

Reflektování na výkon v1

V případě problémů s výkonem, které jsme provedli v předchozí části, můžeme identifikovat dvě hlavní třídy problémů:

  • některé požadavky vyžadují, aby bylo možné vystavit více dotazů za účelem shromáždění všech dat, která potřebujeme vrátit.
  • Některé dotazy nefiltrují klíč oddílu kontejnerů, které cílí, což vede k zablokování, které brání naší škálovatelnosti.

Pojďme vyhodnotit každý z těchto problémů, počínaje prvním z nich.

V2: představení denormalizace pro optimalizaci čtení dotazů

Důvodem, proč musíme vydávat další žádosti v některých případech, je, že výsledky počátečního požadavku neobsahují všechna data, která potřebujeme vrátit. Když pracujete s nerelačním úložištěm dat, jako je Azure Cosmos DB, tento druh problému se často vyřeší tím, že se denormalizace dat v naší datové sadě vyřeší.

V našem příkladu upravujeme položky post za účelem přidání uživatelského jména autora příspěvku, počtu komentářů a počtu podobných:

{
    "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>"
}

Také upravujeme komentáře a podobné položky pro přidání uživatelského jména 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 podobných počtů

To, co chceme dosáhnout, je to, že při každém přidání komentáře nebo podobného příspěvku také zvýšíme commentCount nebo likeCount v odpovídajícím příspěvku. Jak posts je náš kontejner rozdělený na oddíly postId , nová položka (komentář nebo jako) a její odpovídající příspěvek do stejného logického oddílu. V důsledku toho můžeme tuto operaci provést pomocí uložené procedury .

Nyní při vytváření komentáře ([C3]) místo pouhého přidávání nové položky do posts kontejneru zavoláme následující uloženou proceduru v tomto kontejneru:

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 vezme ID příspěvku a tělo nového komentáře jako parametry a pak:

  • Načte příspěvek.
  • zvýší commentCount
  • nahradí příspěvek.
  • Přidá nový komentář.

Protože uložené procedury jsou spouštěny jako atomické transakce, hodnota commentCount a skutečný počet komentářů bude vždy zůstat synchronizován.

Zjevně můžeme zavolat podobnou uloženou proceduru, když přidáváme nové, podobně jako k zvýšení likeCount .

Denormalizace uživatelských jmen

Uživatelské jméno vyžaduje jiný přístup, protože uživatelé nesedí pouze v různých oddílech, ale v jiném kontejneru. Když musíme denormalizovat data napříč oddíly a kontejnery, můžeme použít kanál změnzdrojového kontejneru.

V našem příkladu používáme kanál změn users kontejneru, který reaguje vždycky, když uživatelé aktualizují své uživatelské jméno. V takovém případě jsme změnu rozšířili voláním jiné uložené procedury na posts kontejneru:

Denormalizace uživatelských jmen do kontejneru příspěvky

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 vezme ID uživatele a nového uživatelského jména uživatele jako parametry a potom:

  • Načte všechny položky, které odpovídají userId (které mohou být příspěvky, komentáře nebo podobné položky).
  • pro každou z těchto položek
    • nahrazuje userUsername
    • nahradí položku.

Důležité

Tato operace je náročná, protože vyžaduje, aby se tato uložená procedura spustila na všech oddílech posts kontejneru. Předpokládáme, že většina uživatelů při registraci zvolí vhodné uživatelské jméno a nemění ho, takže se tato aktualizace spustí jenom zřídka.

Jaké jsou přínosy pro zvýšení výkonu v2?

F2 Načtení příspěvku

Teď, když je naše denormalizace na svém místě, musíme jenom načíst jednu položku, která tento požadavek zpracuje.

Načtení jedné položky z kontejneru příspěvky

Latence Poplatek za RU Výkon
2 MS 1 RU

Dotaz Výpis komentáře příspěvku

Tady můžeme vyprázdnit žádosti o další požadavky, které načítají uživatelská jména a končí jediným dotazem, který filtruje klíč oddílu.

Načítání všech komentářů k příspěvku

Latence Poplatek 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.

Načtení všech podobně jako u příspěvku

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.

Diagram, který zobrazuje dotaz na výpis příspěvků uživatele v krátké formě.

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á:

  1. Tento požadavek musí vyfiltrovat, userId protože chceme načíst všechny příspěvky pro konkrétního uživatele.
  2. Nefunguje dobře, protože se provádí na posts kontejneru, který není rozdělený na oddíly userId
  3. 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
  4. 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 type položky uživatele pole pro odlišení uživatelů od příspěvků.
  • do položky uživatele jsme také přidali userId pole, které je redundantní s id polem, ale je potřeba, protože users kontejner je teď rozdělený na oddíly userId (a ne id jako 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.

Denormalizace příspěvků do kontejneru uživatelů

Nyní můžeme směrovat dotaz do users kontejneru a filtrovat klíč oddílu kontejneru.

Načítání všech příspěvků pro uživatele

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:

Diagram znázorňující dotaz, ve kterém jsou uvedeny poslední příspěvky vytvořené v krátké formě.

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:

Denormalizace příspěvků do kontejneru informačního kanálu

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:

Načítají se nejnovější příspěvky.

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: