Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Skapa och underhålla separata uppslagstabeller för data som program ofta använder i frågor när ett datalager inte tillhandahåller lämpliga sekundära index. Den här metoden förbättrar läsprestanda genom att undvika fullständiga datagenomsökningar när frågor inte använder primärnyckeln eller partitionsnyckeln.
Kontext och problem
Många datalager organiserar data för en samling entiteter med hjälp av primärnyckeln. Ett program kan använda den här nyckel för att hitta och hämta data. Följande bild visar ett exempel på ett datalager med kundinformation ordnad efter primärnyckeln, kund-ID.
Bilden visar en tabell med två kolumner med kundposter. Den första kolumnen, Primärnyckel (kund-ID), innehåller kund-ID 1 till 9 följt av en ellips, ID 1000 och en annan ellips. Den andra kolumnen, Customer Data, innehåller kunddata som består av ett efternamn och en ort följt av en ellips. Synliga exempel är ID 1, som mappar till efternamnet Smith och staden Redmond och ID 2, som mappar till efternamnet Jones och staden Seattle. En annan rad visar Smith i Chicago, och en annan visar Smith i Redmond. Ytterligare en rad visar att Jones är i Chicago.
Även om den primära nyckeln är värdefull för frågor som hämtar data baserat på värdet för den här nyckeln, kan ett program som behöver hämta data baserat på något annat fält inte använda den primära nyckeln för den frågan. I kundexemplet kan ett program inte använda den primära nyckeln, Kund-ID, för att hämta kunder om det efterfrågar data enbart genom att referera till värdet för något annat attribut, till exempel den stad där kunden finns. För att utföra en fråga som endast refererar till staden kan programmet behöva hämta och undersöka varje kundpost, vilket kan vara en långsam process.
Många relationsdatabashanteringssystem har stöd för sekundära index. Ett sekundärt index är en separat datastruktur som organiseras av ett eller flera icke-primära (sekundära) nyckelfält. Ett sekundärt index anger var data för varje indexerat värde lagras. Objekten i ett sekundärt index sorteras vanligtvis efter värdet för de sekundära nycklarna för att möjliggöra snabb datasökning. Databashanteringssystemet underhåller vanligtvis dessa index automatiskt.
Relationsdatabaser tillåter att flera sekundära index stöder olika frågemönster. I en kundtabell i en relationsdatabas där kund-ID:t är den primära nyckeln är det till exempel fördelaktigt att lägga till ett sekundärt index över fältet Stad om programmet ofta söker efter kunder efter den stad där de finns.
Även om sekundära index är vanliga i relationssystem ger inte alla datalager en motsvarande funktion. Vissa datalager saknar sekundära index, medan andra tillhandahåller index som inte uppfyller en arbetsbelastnings fråge-, partitionerings- eller prestandakrav. I dessa fall måste program välja mellan fullständiga genomsökningar och manuell indexhantering.
Lösning
Skapa en indextabell som organiserar data efter en angiven nyckel. I följande avsnitt beskrivs tre vanliga strategier för att strukturera en indextabell. De två efterföljande avsnitten beskriver användning för indextabeller i specifika scenarier.
Standardstrategier för strukturering
Följande strategier används ofta för att strukturera en indextabell. Välj en strategi baserat på antalet sekundära index som ditt scenario kräver och typen av frågor som programmet utför.
Fullständig avnormalisering
Fullständig avnormalisering duplicerar data i varje indextabell men ordnar dem med andra nycklar än primärnyckeln. Följande bild visar indextabeller som organiserar samma kundinformation efter Stad och Efternamn.
Den här strategin fungerar bra för läsintensiva arbetsbelastningar där data ändras sällan. När uppdateringshastigheten ökar medför det bearbetningsoverhead att underhålla varje kopia (se Konsistenskomplexitet). För datauppsättningar med stora volymer kan lagring av kopiorna också kräva betydande utrymme.
Normaliserat index
En normaliserad indextabell organiserar data efter andra nycklar än primärnyckeln. Den normaliserade indextabellen refererar till ursprungliga data med hjälp av primärnyckeln i stället för att duplicera dessa data, enligt följande bild. Den ursprungliga informationen kallas en faktatabell.
Tip
Här innebär faktatabellen den auktoritativa källtabell som refereras till av ett index. Det innebär inte en dimensionell datamodell.
Den här metoden sparar utrymme och minskar kostnaderna för att underhålla dubblettdata. Nackdelen är att ett program måste utföra två uppslagsåtgärder för att hitta data med hjälp av en sekundär nyckel. Programmet måste hitta den primära nyckeln för data i indextabellen och sedan använda primärnyckeln för att leta upp data i faktatabellen.
Partiell avnormalisering
Partiell avnormalisering skapar indextabeller som duplicerar fält som ofta hämtas och ordnas efter andra nycklar än primärnyckeln. Faktatabellen refereras till för att få åtkomst till fält som används mindre ofta. Följande bild visar hur data som används ofta dupliceras i varje indextabell.
Den här strategin balanserar de två första metoderna. Du kan snabbt hämta data för vanliga frågor med hjälp av en enda sökning, medan utrymmes- och underhållskostnaderna inte är lika viktiga som att duplicera hela datauppsättningen.
Sammansatta nycklar
Vissa program frågar ofta efter data genom att ange en kombination av värden, till exempel "Hitta alla kunder som bor i Redmond och som har ett efternamn på Smith". I det här fallet skapar du indexnycklar från flera attribut, till exempel attributen Town och LastName i det här fallet.
Använd en kodning som bevarar komponentgränser så att olika värdekombinationer inte kan producera samma nyckel. Om frågor är beroende av nyckelordning kontrollerar du också att kodningen bevarar den sorteringsordning som krävs enligt datalagrets regler för nyckelsortering.
Följande bild visar en indextabell baserad på sammansatta nycklar. Nycklarna sorteras efter Stad och sedan efter Efternamn för poster som har samma värde för Stad.
Diagrammet innehåller en indextabell till vänster och en faktatabell till höger. Faktatabellen organiserar kunddata efter primärnyckel, kund-ID. Varje kunddatarad innehåller ett kund efternamn, en stad och en ellips som anger andra data. Indextabellen organiseras av en sammansatt nyckel som kombinerar Town och LastName. Den andra kolumnen, Kundreferens (ID) och vanliga data som efterfrågas, innehåller ett kund-ID och en ellips. Pilarna sträcker sig från indextabellrader till faktatabellen, där varje pil pekar på den kund-ID-rad som indexposten refererar till. De korsande pilarna visar att poster som sorterats enligt den sammansatta nyckeln kan hänvisa till kundrader på olika positioner i faktatabellen.
Indexera tabeller över fragmenterade data
Indextabeller kan påskynda frågeåtgärder över fragmenterade data. De är särskilt användbara när shardnyckeln är hashad. Följande bild visar ett exempel där shardnyckeln är en hash för kund-ID:t. Indextabellen organiserar poster efter icke-hashade värden, Town och LastName, och lagrar motsvarande hashade shardnyckel med varje post.
Den här lösningen stöder intervall- och ordnade uppslagningar på icke-hashade värden samtidigt som den tillhandahåller den dirigeringsinformation som behövs för att hämta varje post från rätt shard. En fråga som "Hitta alla kunder som bor i Redmond" kan till exempel hitta matchande objekt i ett sammanhängande block i indextabellen. Programmet följer sedan referenserna till kunddata med hjälp av de shardnycklar som lagras i indextabellen.
Problem och överväganden
Tänk på följande när du bestämmer hur du ska implementera det här mönstret:
Underhållskostnader. Att underhålla sekundära index kan ge betydande omkostnader. Analysera och förstå de frågor som programmet använder. Skapa endast indextabeller när du förmodligen använder dem regelbundet. Skapa inte spekulativa indextabeller för att stödja frågor som ett program inte utför eller utför endast ibland. När antalet frågemönster växer växer antalet indextabeller och var och en lägger till driftytan för att övervaka, underhålla och felsöka. Väg frågefördelen för varje indextabell mot driftkostnaden för att underhålla en annan härledd datastruktur. Granska regelbundet befintliga indextabeller för att identifiera och ta bort alla som inte längre efterfrågas.
Kostnad för lagring och dataflöde. Om du duplicerar data i en indextabell ökar lagringskostnaderna i förhållande till antalet indextabeller och storleken på kopierade fält. Att underhålla flera kopior av data ökar också arbetet. Varje skrivning till en indextabell förbrukar dataflödeskapacitet, till exempel transaktioner mot lagringskontots gränser i Azure Table Storage eller enheter för begäran i Azure Cosmos DB. Kostnaden sträcker sig utanför lagringen till dataflödet på skrivsidan.
Dubbel uppslagsstraff. Om du vill implementera en indextabell som en normaliserad struktur som refererar till ursprungsdata krävs ett program som kör två sökåtgärder för att hitta data. Den första åtgärden söker igenom indextabellen för att hämta den primära nyckeln. Den andra åtgärden använder den primära nyckeln för att hämta data.
Konsistenskomplexitet Om ett system innehåller ett antal indextabeller över stora datauppsättningar kan det vara svårt att upprätthålla konsekvens mellan indextabeller och ursprungliga data. Om källdata- och indexposterna inte kan uppdateras i samma transaktion utformar du programmet kring en eventuell konsekvensmodell. Registrera varje källändring varaktigt innan skrivningen bekräftas. Använd till exempel en databasändringsfeed, använd mönstret Transaktionell utkorg för att skriva en utkorgspost i samma transaktion som källändringen eller ange ett kommando innan du ändrar källdata. I den kommandobaserade metoden använder du en arbetare för att bearbeta kommandot och uppdatera källdata och dess index. Uppdatera inte källdata och publicera sedan ett indexuppdateringsmeddelande oberoende av varandra, eftersom ett fel mellan dessa åtgärder kan lämna indexet inaktuellt.
Utforma den asynkrona konsumenten så att den är idempotent eftersom meddelandeleverans och återförsök kan orsaka att samma uppdatering körs mer än en gång. Uppdateringar för samma källpost kan också komma i fel ordning. Inkludera en källversion eller sekvensnummer i varje indexuppdatering och tillämpa endast en uppdatering om den är nyare än versionen i indexet. För borttagningar behåller du en versionsbelagd gravsten eller ett motsvarande högvattenmärke så att en fördröjd äldre uppdatering inte kan återskapa den borttagna indexposten. Under intervallet mellan källdataskrivningen och den asynkrona indexuppdateringen kan frågor mot indextabellen returnera inaktuella referenser till poster som har uppdaterats eller tagits bort i källdata och de kan utelämna nyligen tillagda poster.
Partitionering av indextabeller. Indextabeller kan själva vara partitionerade eller shardade, vilket ökar komplexiteten i routning av frågor och kräver att partitioneringsstrategin är anpassad till de frågemönster som indexet är utformat för att stödja.
När du ska använda det här mönstret
Använd det här mönstret när ett program ofta behöver hämta data med hjälp av en annan nyckel än den primära (eller shard)-nyckeln, och datalagret inte har inbyggt stöd för sekundära index eller om dess interna index inte uppfyller arbetsbelastningens fråge-, partitionerings- eller prestandakrav.
Det här mönstret kanske inte är lämpligt när:
Data är flyktiga. Data ändras så ofta att skrivfrekvensen överskrider den hastighet med vilken indextabeller kan uppdateras asynkront. Fönstret för inaktuellhet växer tills indexet är permanent inaktuellt, vilket gör det ineffektivt och gör lagrings- och dataflödeskostnaderna för att underhålla indextabellen större än eventuella frågebesparingar.
Du har icke-diskriminerande nycklar. Ett fält som valts som sekundärnyckel för en indextabell är icke-urskillningslöst och kan bara ha en liten uppsättning värden (till exempel ett booleskt fält som registrerar om ett objekt är aktivt). Indextabellen medför full lagrings- och genomströmningskostnad men ger minimal frågeselektivitet.
Datavärden har en skev fördelning. Balansen mellan datavärdena för ett fält som valts som sekundärnyckel för en indextabell är mycket skev. Om till exempel 90 procent av posterna innehåller samma värde i ett fält kan det skapa och underhålla en indextabell för att söka efter data baserat på det här fältet skapa mer omkostnader än sekventiell genomsökning av data. Men om frågor ofta riktar sig mot värden som ligger i de återstående 10 procenten kan det här indexet fortfarande vara användbart.
Design av arbetsbelastning
En arkitekt bör utvärdera hur du använder indextabellmönstret i arbetsbelastningsdesignen för att uppfylla de mål och principer som beskrivs i Azure Well-Architected Framework-pelarna. Följande tabell innehåller vägledning om hur det här mönstret stöder målen för varje pelare.
| Grundpelare | Så här stöder det här mönstret pelarmål |
|---|---|
| Tillförlitlighet hjälper din arbetsbelastning att uppfylla sina återhämtnings- och återställningsmål genom att skapa redundans och bevara funktioner vid fel. | Asynkront indexunderhåll kan förhindra tillfälliga indexuppdateringsfel från att blockera skrivningar av källdata. Idempotent bearbetning, dead-letter-hantering, övervakning och avstämning hjälper till att återställa indexkonsistens efter fel. - RE:07 Självbevarande - RE:10 Övervakning |
| Prestandaeffektivitet hjälper din arbetsbelastning effektivt uppfylla kraven genom optimering av skalning, data och kod. | Indextabeller hjälper till att aktivera snabba sökningar på icke-primära nyckelfält utan att det krävs fullständiga datagenomsökningar. För fragmenterade datalager kan indextabeller ordna poster efter icke-hashade värden för att stödja intervall- och beställningsfrågor som enbart shardnyckeln inte kan hantera effektivt. - PE:05 Skalning och partitionering - PE:08 Dataprestanda |
Som med alla designbeslut, om detta mönster inför kompromisser inom en pelare, bör du överväga dem mot målen för de andra pelarna.
Example
Överväg ett program som lagrar information om filmer. Anta att katalogen är stor och läsintensiv, att varje film har en primär genre, att sökningar på skådespelare är frekventa, att data om rollbesättningen ändras sällan och att en kort fördröjning i indexeringen är acceptabel. Table Storage lagrar varje entitet som en strukturerad uppsättning namngivna egenskaper. Varje entitet innehåller en PartitionKey, en RowKey, och en tidsstämpel och entiteter i samma tabell kan ha olika uppsättningar egenskaper.
Table Storage använder en sammansatt primärnyckel som består av PartitionKey och RowKey. Värdet PartitionKey avgör i vilken partition en entitet lagras. I en partition RowKey identifierar värdet unikt en entitet. Table Storage är optimerat för frågor som anger båda nycklarna eller hämtar ett sammanhängande intervall med radnyckelvärden inom en partition.
Tip
Table Storage stöder transaktionsuppdateringar för entiteter i samma tabell och partition via entitetsgrupptransaktioner. En transaktion kan inte sträcka sig över en faktatabell och en separat indextabell. Om du vill uppdatera en faktaentitet och indexentiteter atomiskt lagrar du dem i samma tabell med samma PartitionKey. Entitetsgrupptransaktioner är begränsade till 100 entiteter per batch med en maximal nyttolast på 4 MiB.
I det här exemplet skapar du en Azure tabell med partitioner för varje genre genom att använda en kodad genreidentifierare som partitionsnyckel och en stabil, unik filmidentifierare som radnyckel. Lagra genre- och filmnamnen som egenskaper. Följande bild använder läsbara namn i stället för identifierare för att göra exemplet enklare att följa.
Den här metoden är mindre effektiv om programmet även måste söka efter filmer efter skådespelare. I så fall skapar du en separat Azure tabell som fungerar som en indextabell. Använd en kodad, stabil aktörsidentifierare som partitionsnyckel och filmidentifierare som radnyckel. Lagra skådespelare och filmnamn som egenskaper. Följande bild använder läsbara namn i stället för identifierare. Om en film har fler än en skådespelare förekommer samma film i flera partitioner.
Följande bild visar aktörsindextabellen.
Genomgång av design
Filmtabellen använder genre som partitionsnyckel, vilket innebär att frågor som filtrerar efter genre körs effektivt som partitionsskanningar över sammanhängande intervall av radnycklar. Table Storage stöder dock endast ett klustrat index på PartitionKey och RowKey. Den har inga sekundära index. En fråga som "hitta alla filmer med en specifik aktör i huvudrollen" kräver en fullständig tabellgenomsökning över varje genrepartition, vilket är dyrt i stor skala.
Aktörsindextabellen åtgärdar den här begränsningen genom att återställa åtkomstmönstret. Varje aktörsidentifierare blir en partitionsnyckel och varje filmidentifierare blir en radnyckel, så aktörsbaserade frågor kan utföras som effektiva partitionsuppslagningar. Eftersom varje partition endast innehåller en aktörs filmer returnerar frågan ett sammanhängande intervall med entiteter utan att skanna orelaterade data.
Eftersom film- och aktörsposter använder separata tabeller och partitionsnycklar kan dessa poster inte dela en entitetsgrupptransaktion. Upprätthåll aktörsindexet med hjälp av en beständig mekanism för asynkron ändringsinsamling, och utforma applikationen så att den tolererar att frågeresultat kan vara kortvarigt inaktuella.
Indextabellen tillämpar partiell avnormalisering: varje post duplicerar fält som används ofta (till exempel namnen på andra aktörer) så att de vanligaste frågorna kan besvaras enbart från indextabellen med ett enda uppslag. För fält som används mer sällan innehåller posten genrepartitionsnyckeln från den ursprungliga filmtabellen, vilket möjliggör en målinriktad punktfråga till genrepartitionen för att hämta hela posten. Den här designen balanserar frågehastigheten mot lagringskostnader och underhållskostnader.
Nästa steg
Vägledning för frågedesign för Table Storage beskriver sekundära indexmönster som använder
PartitionKeyochRowKey, inklusive metoder för att lagra indexposter i samma partition eller i separata partitioner.Strategier för datapartitionering förklarar hur du väljer partitions- och radnycklar baserat på frågemönster, datadistribution, transaktionskrav och skalbarhetsmål.
Arkitekturstrategier för att optimera dataprestanda ger vägledning för att utvärdera frågemönster, index, partitioner och övervakningskrav.
Konsekvensnivåer i Azure Cosmos DB beskriver de konsekvensmodeller som är relevanta när du underhåller indextabeller i Azure Cosmos DB.
Relaterade resurser
Följande mönster kan också vara relevanta när du implementerar det här mönstret:
Mönster för horisontell partitionering. Indextabellmönstret används ofta tillsammans med data som har partitionerats horisontellt (shards). Sharding-mönstret beskriver hur du delar upp ett datalager i en uppsättning shards.
Mönster för materialiserad vy. I stället för att indexera data för att stödja frågor som sammanfattar data kan det vara lämpligare att skapa en materialiserad vy av data. Det här mönstret beskriver hur du genererar förifyllda vyer över data för att stödja effektiva sammanfattningsfrågor.
Utkorgsmönster för transaktioner. Använd mönstret Transaktionell utkorg för att publicera ändringar för asynkront indexunderhåll på ett tillförlitligt sätt när källdata och indexposter inte kan uppdateras i en transaktion.