Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Azure Cosmos DB is een schemaagnostische database waarmee u uw toepassing kunt herhalen zonder dat u te maken hebt met schema- of indexbeheer. Standaard indexeert Azure Cosmos DB elke eigenschap automatisch voor alle items in uw container zonder dat u een schema hoeft te definiëren of secundaire indexen hoeft te configureren.
In dit artikel wordt uitgelegd hoe Azure Cosmos DB gegevens indexeert en hoe deze indexen gebruikt om de queryprestaties te verbeteren. Het is raadzaam om deze sectie te doorlopen voordat u het indexeringsbeleid aanpast.
Van items naar bomen
Telkens wanneer een item wordt opgeslagen in een container, wordt de inhoud ervan als een JSON-document geprojecteerd en vervolgens geconverteerd naar een structuurweergave. Deze conversie betekent dat elke eigenschap van dat item wordt weergegeven als een knooppunt in een boomstructuur. Er wordt een pseudo-hoofdknooppunt gemaakt als ouder voor alle eigenschappen op het hoogste niveau van het item. De bladknooppunten bevatten de werkelijke scalaire waarden die door een item worden overgedragen.
Bekijk bijvoorbeeld dit item:
{
"locations": [
{ "country": "Germany", "city": "Berlin" },
{ "country": "France", "city": "Paris" }
],
"headquarters": { "country": "Belgium", "employees": 250 },
"exports": [
{ "city": "Moscow" },
{ "city": "Athens" }
]
}
Deze boom vertegenwoordigt het JSON-voorbeelditem.
Diagram van het vorige JSON-item dat wordt weergegeven als een boomstructuur.
Let op hoe arrays in de structuur worden gecodeerd: elk element in een array krijgt een tussenliggend knooppunt met als label de index van dat element binnen de array (0, 1 enzovoort).
Van bomen tot eigenschapspaden
Azure Cosmos DB items transformeert in bomen, omdat het systeem kan verwijzen naar eigenschappen met behulp van hun paden binnen die bomen. Om het pad voor een eigenschap op te halen, kunnen we de boom van het wortelknooppunt naar die eigenschap traverseren en de labels van elk doorlopen knooppunt samenvoegen.
Hier volgen de paden voor elke eigenschap uit het eerder beschreven voorbeelditem:
- : "Duitsland"
- : "Berlijn"
- : "Frankrijk"
- : "Parijs"
- : "België"
- : 250
- : "Moskou"
- : "Athene"
Azure Cosmos DB indexeert het pad van elke eigenschap en de bijbehorende waarde wanneer een item wordt geschreven.
Indextypen
Azure Cosmos DB ondersteunt momenteel drie typen indexen. U kunt deze indextypen configureren bij het definiëren van het indexeringsbeleid.
Bereikindex
Bereikindexen zijn gebaseerd op een geordende boomhartige structuur. Het type bereikindex wordt gebruikt voor:
Gelijkheidsverzoeken
SELECT * FROM container c WHERE c.property = 'value'SELECT * FROM c WHERE c.property IN ("value1", "value2", "value3")Gelijkheidsmatch op een matrixelement
SELECT * FROM c WHERE ARRAY_CONTAINS(c.tags, "tag1")Bereikqueries
SELECT * FROM container c WHERE c.property > 'value'Notitie
Werkt voor , , , ,
Controleren op de aanwezigheid van een eigenschap:
SELECT * FROM c WHERE IS_DEFINED(c.property)Systeemfuncties voor Strings:
SELECT * FROM c WHERE CONTAINS(c.property, "value")SELECT * FROM c WHERE STRINGEQUALS(c.property, "value")Query 's:
SELECT * FROM container c ORDER BY c.propertyQuery 's:
SELECT child FROM container c JOIN child IN c.properties WHERE child = 'value'
Bereikindexen kunnen worden gebruikt voor scalaire waarden (tekenreeks of getal). Het standaardindexeringsbeleid voor nieuw gemaakte containers dwingt bereikindexen af voor een willekeurige tekenreeks of een willekeurig getal. Zie Beheerbeleidsregels in Azure Cosmos DB voor meer informatie over het configureren van bereikindexen.
Notitie
Een component dat sorteert op één eigenschap heeft altijd een bereikindex nodig en zal falen als het pad waarnaar het verwijst er geen heeft. Op dezelfde manier heeft een query die door meerdere eigenschappen wordt geordend , altijd een samengestelde index nodig.
Ruimtelijke index
Ruimtelijke indexen maken efficiënte query's mogelijk voor georuimtelijke objecten, zoals punten, lijnen, veelhoeken en multipolygonen. Deze query's gebruiken , trefwoorden. Hier volgen enkele voorbeelden die gebruikmaken van het type ruimtelijke index:
Geo-ruimtelijke afstandsqueries
SELECT * FROM container c WHERE ST_DISTANCE(c.property, { "type": "Point", "coordinates": [0.0, 10.0] }) < 40Georuimtelijk in queries
SELECT * FROM container c WHERE ST_WITHIN(c.property, {"type": "Point", "coordinates": [0.0, 10.0] })Georuimtelijke snijdingsqueries
SELECT * FROM c WHERE ST_INTERSECTS(c.property, { 'type':'Polygon', 'coordinates': [[ [31.8, -5], [32, -5], [31.8, -5] ]] })
Ruimtelijke indexen kunnen worden gebruikt voor geoJSON-objecten die correct zijn opgemaakt. Punten, LineStrings, Polygonen en MultiPolygons worden momenteel ondersteund. Zie Beleid voor indexering in Azure Cosmos DB voor meer informatie over het configureren van ruimtelijke indexen.
Belangrijk
Azure Cosmos DB-ruimtelijke indexering is niet gelijk aan het indexgedrag van MongoDB 2dsphere, zelfs niet wanneer de Azure Cosmos DB voor MongoDB-API wordt gebruikt.
Hoewel Cosmos DB georuimtelijke query's ondersteunt via de systeemeigen ruimtelijke index en functies zoals , en , wordt het georuimtelijke query-engine of uitvoeringsmodel van MongoDB niet geïmplementeerd. Als gevolg hiervan:
- Het maken van een index in de MongoDB-API garandeert niet dezelfde prestatiekenmerken als MongoDB.
- Queryuitvoeringsplannen en optimalisatiestrategieën verschillen tussen Cosmos DB en MongoDB.
- Toepassingen die vanuit MongoDB migreren, kunnen verschillende prestatiegedrag zien voor georuimtelijke query's, zelfs wanneer indexen met succes worden gemaakt.
Voor de beste prestaties controleert u of uw gegevens zijn opgeslagen als geldig GeoJSON en gebruikt u de ruimtelijke Cosmos DB-functies die zijn geoptimaliseerd voor de systeemeigen ruimtelijke index.
Samengestelde indexen
Samengestelde indexen verhogen de efficiëntie wanneer u bewerkingen uitvoert op meerdere velden. Het samengestelde indextype wordt gebruikt voor:
queries op meerdere eigenschappen:
SELECT * FROM container c ORDER BY c.property1, c.property2Query's met een filter en . Deze query's kunnen gebruikmaken van een samengestelde index als de filtereigenschap wordt toegevoegd aan de component.
SELECT * FROM container c WHERE c.property1 = 'value' ORDER BY c.property1, c.property2Query's met een filter op twee of meer eigenschappen waarbij ten minste één eigenschap een gelijkheidsfilter is:
SELECT * FROM container c WHERE c.property1 = 'value' AND c.property2 > 'value'
Zolang één filterpredicaat een van de indextypen gebruikt, evalueert de query-engine dat eerst voordat de rest wordt gescand. Als u bijvoorbeeld een SQL-query hebt, zoals :
Deze query filtert eerst op vermeldingen waarbij firstName = "Andrew" met behulp van de index. Vervolgens worden alle firstName = "Andrew"-vermeldingen doorgegeven via een volgende pijplijn om het CONTAINS-filterpredicaat te evalueren.
U kunt query's versnellen en volledige containerscans voorkomen wanneer u functies gebruikt die een volledige scan uitvoeren, zoals CONTAINS. U kunt meer filterpredicaten toevoegen die gebruikmaken van de index om deze query's sneller te maken. De volgorde van filtercomponenten is niet belangrijk. De query-engine bepaalt welke predicaten selectiever zijn en voer de query dienovereenkomstig uit.
Zie Indexeringsbeleid beheren in Azure Cosmos DB voor meer informatie over het configureren van samengestelde indexen.
Vectorindexen
Vectorindexen verhogen de efficiëntie bij het uitvoeren van vectorzoekopdrachten met behulp van de systeemfunctie. Vectorzoekopdrachten hebben aanzienlijk lagere latentie, hogere doorvoer en minder RU-verbruik bij het gebruik van een vectorindex. Azure Cosmos DB for NoSQL ondersteunt vector-insluitingen (tekst, afbeelding, multimodale, enzovoort) onder 4.096 afmetingen. Zie voorbeelden van vectorindexeringsbeleid voor meer informatie over het configureren van vectorindexen.
vectorzoekqueries:
SELECT TOP 10 * FROM c ORDER BY VectorDistance(c.vector1, c.vector2)Projectie van de gelijkenisscore in zoekopdrachten met vectoren.
SELECT TOP 10 c.name, VectorDistance(c.vector1, c.vector2) AS SimilarityScore FROM c ORDER BY VectorDistance(c.vector1, c.vector2)Bereikfilters voor de overeenkomstscore.
SELECT TOP 10 * FROM c WHERE VectorDistance(c.vector1, c.vector2) > 0.8 ORDER BY VectorDistance(c.vector1, c.vector2)
Belangrijk
Op dit moment zijn vectorbeleid en vectorindexen onveranderbaar na het maken. Als u wijzigingen wilt aanbrengen, maakt u een nieuwe verzameling.
Indexgebruik
Er zijn vijf manieren waarop de query-engine queryfilters kan evalueren, gesorteerd op meest efficiënt tot minst efficiënt:
- Indexzoeken
- Nauwkeurige indexscan
- Uitgevouwen indexscan
- Volledige indexscan
- Volledige scan
Wanneer u eigenschapspaden indexeren, gebruikt de query-engine automatisch de index zo efficiënt mogelijk. Afgezien van het indexeren van nieuwe eigenschapspaden hoeft u niets te configureren om te optimaliseren hoe query's de index gebruiken. De RU-kosten van een query zijn een combinatie van de RU-kosten van het indexgebruik en de RU-kosten van het laden van items.
De volgende tabel bevat een overzicht van de verschillende manieren waarop indexen worden gebruikt in Azure Cosmos DB:
| Type indexzoekactie | Beschrijving | Algemene voorbeelden | RU-belasting door indexgebruik | RU-kosten voor het laden van items uit transactionele gegevensopslag |
|---|---|---|---|---|
| Indexzoeken | Lees alleen de vereiste geïndexeerde waarden en laad alleen overeenkomende items uit de operationele gegevensopslag. | Gelijkheidsfilters, IN | Constante per gelijkheidsfilter | Verhogingen op basis van het aantal items in queryresultaten |
| Nauwkeurige indexscan | Binaire zoekopdracht van geïndexeerde waarden en laad alleen overeenkomende items uit het transactionele gegevensarchief | Bereikvergelijkingen (, , =, of =), Begint met | Vergelijkbaar met het zoeken naar indexen, neemt enigszins toe op basis van de kardinaliteit van geïndexeerde eigenschappen | Verhogingen op basis van het aantal items in queryresultaten |
| Uitgevouwen indexscan | Geoptimaliseerde zoekopdracht (maar minder efficiënt dan een binaire zoekopdracht) van geïndexeerde waarden en laad alleen overeenkomende items uit het transactionele gegevensarchief | StartsWith (niet-hoofdlettergevoelig), StringEquals (niet-hoofdlettergevoelig) | Neemt enigszins toe op basis van de kardinaliteit van geïndexeerde eigenschappen | Verhogingen op basis van het aantal items in queryresultaten |
| Volledige indexscan | Afzonderlijke set geïndexeerde waarden lezen en alleen overeenkomende items uit het transactionele gegevensarchief laden | Bevat, EndsWith, RegexMatch, LIKE | Wordt lineair verhoogd op basis van de kardinaliteit van geïndexeerde eigenschappen | Verhogingen op basis van het aantal items in queryresultaten |
| Volledige scan | Alle items uit het transactionele gegevensarchief laden | Boven, onder | N.v.t. | Verhoogt op basis van het aantal items in de container |
Bij het schrijven van query's moet u filterpredicaten gebruiken die de index zo efficiënt mogelijk gebruiken. Als u bijvoorbeeld voor uw use-case werkt, moet u ervoor kiezen om een nauwkeurige indexscan uit te voeren in plaats van een volledige indexscan.
Details van indexgebruik
In deze sectie vindt u meer informatie over hoe query's indexen gebruiken. Dit detailniveau is niet nodig om te leren hoe u kunt beginnen met Azure Cosmos DB, maar wordt in detail gedocumenteerd voor nieuwsgierige gebruikers. We verwijzen naar het voorbeelditem dat eerder in dit document is gedeeld:
Voorbeelditems:
{
"id": 1,
"locations": [
{ "country": "Germany", "city": "Berlin" },
{ "country": "France", "city": "Paris" }
],
"headquarters": { "country": "Belgium", "employees": 250 },
"exports": [
{ "city": "Moscow" },
{ "city": "Athens" }
]
}
{
"id": 2,
"locations": [
{ "country": "Ireland", "city": "Dublin" }
],
"headquarters": { "country": "Belgium", "employees": 200 },
"exports": [
{ "city": "Moscow" },
{ "city": "Athens" },
{ "city": "London" }
]
}
Azure Cosmos DB maakt gebruik van een omgekeerde index. De index werkt door elk JSON-pad toe te kennen aan de set items die die waarde bevatten. De item-id-toewijzing wordt weergegeven op veel verschillende indexpagina's voor de container. Hier volgt een voorbeelddiagram van een omgekeerde index voor een container die de twee voorbeelditems bevat:
| Pad | Weergegeven als | Lijst met item-ID's |
|---|---|---|
| /locations/0/country | Duitsland | 1 |
| /locations/0/country | Ierland | 2 |
| /locations/0/stad | Berlijn | 1 |
| /locations/0/stad | Dublin | 2 |
| /locations/1/country | Frankrijk | 1 |
| /locations/1/stad | Parijs | 1 |
| /hoofdkantoor/land | België | 1, 2 |
| /hoofdkantoor/werknemers | 200 | 2 |
| /hoofdkantoor/werknemers | 250 | 1 |
De omgekeerde index heeft twee belangrijke kenmerken:
- Voor een bepaald pad worden waarden in oplopende volgorde gesorteerd. Daarom kan de query-engine eenvoudig worden uitgevoerd vanuit de index.
- Voor een bepaald pad kan de query-engine de afzonderlijke set mogelijke waarden scannen om de indexpagina's te identificeren waar de resultaten zijn.
De query-engine kan de omgekeerde index op vier verschillende manieren gebruiken:
Indexzoeken
Houd rekening met de volgende query:
SELECT location
FROM location IN company.locations
WHERE location.country = 'France'
Het querypredicaat (filteren op items waar een locatie 'Frankrijk' heeft als land of regio), komt overeen met het pad dat in dit diagram is gemarkeerd:
Diagram van een doorkruising (zoeken) die overeenkomt met een specifiek pad in een boomstructuur.
Omdat deze query een gelijkheidsfilter heeft, kunnen we na het doorlopen van deze structuur snel de indexpagina's identificeren die de queryresultaten bevatten. In dit geval zou de query-engine indexpagina's lezen die item 1 bevatten. Een indexzoeken is de meest efficiënte manier om de index te gebruiken. Met een indexzoeken lezen we alleen de benodigde indexpagina's en laden we alleen de items in de queryresultaten. Daarom zijn de opzoektijd en RU-kosten van indexzoektijd ongelooflijk laag, ongeacht het totale gegevensvolume.
Nauwkeurige indexscan
Houd rekening met de volgende query:
SELECT *
FROM company
WHERE company.headquarters.employees > 200
Het querypredicaat (filteren op items met meer dan 200 werknemers) kan worden geëvalueerd met een nauwkeurige indexscan van het pad. Wanneer u een nauwkeurige indexscan uitvoert, begint de query-engine met een binaire zoekopdracht van de afzonderlijke set mogelijke waarden om de locatie van de waarde voor het pad te vinden. Omdat de waarden voor elk pad in oplopende volgorde worden gesorteerd, is het eenvoudig voor de queryengine om een binaire zoekopdracht uit te voeren. Nadat de query-engine de waarde heeft gevonden, worden alle resterende indexpagina's gelezen (in oplopende richting).
Omdat de query-engine een binaire zoekopdracht kan uitvoeren om te voorkomen dat onnodige indexpagina's worden gescand, hebben nauwkeurige indexscans meestal vergelijkbare latentie en RU-kosten voor indexzoekbewerkingen.
Uitgevouwen indexscan
Houd rekening met de volgende query:
SELECT *
FROM company
WHERE STARTSWITH(company.headquarters.country, "United", true)
Het querypredicaat (filteren op items met een hoofdkantoor op een locatie die begint met hoofdletterongevoelig 'United') kan worden geëvalueerd met een verruimde indexscan van het -pad. Bewerkingen die een uitgebreide indexscan uitvoeren, hebben optimalisaties die kunnen helpen voorkomen dat elke indexpagina moet worden gescand, maar die iets duurder zijn dan de binaire zoekfunctie van een indexscan.
Bij het evalueren van niet-hoofdlettergevoelig controleert de query-engine de index voor verschillende mogelijke combinaties van hoofdletters en kleine letters. Met deze optimalisatie kan de query-engine voorkomen dat de meeste indexpagina's worden gelezen. Verschillende systeemfuncties hebben verschillende optimalisaties die ze kunnen gebruiken om te voorkomen dat elke indexpagina wordt gelezen, zodat ze breed worden gecategoriseerd als uitgebreide indexscan.
Volledige indexscan
Houd rekening met de volgende query:
SELECT *
FROM company
WHERE CONTAINS(company.headquarters.country, "United")
Het query-predicaat (filteren op items die hun hoofdkantoor hebben op een locatie die 'United' bevat) kan worden geëvalueerd door middel van een indexscan van het pad. In tegenstelling tot een nauwkeurige indexscan, scant een volledige indexscan altijd alle verschillende mogelijke waarden om de indexpagina's met resultaten te identificeren. In dit geval wordt uitgevoerd op de index. De indexzoektijd en RU-kosten voor indexscans nemen toe naarmate de kardinaliteit van het pad toeneemt. Met andere woorden, hoe meer mogelijke afzonderlijke waarden de query-engine moet scannen, hoe hoger de latentie en RU-kosten bij het uitvoeren van een volledige indexscan.
Denk bijvoorbeeld aan twee eigenschappen: en . De kardinaliteit van de stad is 5.000 en de kardinaliteit van is 200. Hier volgen twee voorbeeldquery's die elk een CONTAINS-systeemfunctie hebben waarmee een volledige indexscan op de eigenschap wordt uitgevoerd. De eerste query gebruikt meer RU's dan de tweede query omdat de kardinaliteit van de stad hoger is dan .
SELECT *
FROM c
WHERE CONTAINS(c.town, "Red", false)
SELECT *
FROM c
WHERE CONTAINS(c.country, "States", false)
Volledige scan
In sommige gevallen kan de query-engine mogelijk geen queryfilter evalueren met behulp van de index. In dit geval moet de query-engine alle items uit het transactionele archief laden om het queryfilter te evalueren. Volledige scans gebruiken de index niet en hebben RU-kosten die lineair toenemen met de totale gegevensgrootte. Gelukkig zijn bewerkingen die volledige scans vereisen zeldzaam.
Vectorzoekquery's zonder een gedefinieerde vectorindex
Als u geen vectorindexbeleid definieert en de systeemfunctie in een component gebruikt, resulteert dit in een volledige scan en wordt een RU-kosten hoger in rekening gebracht dan wanneer u een vectorindexbeleid hebt gedefinieerd. Gelijkenis, als u gebruikt met de brute-force booleaanse waarde op waar hebt ingesteld, en geen index hebt gedefinieerd voor het vectorpad, treedt er een volledige scan op.
Query's met complexe filterexpressies
In de eerdere voorbeelden hebben we alleen query's overwogen die eenvoudige filterexpressies hadden (bijvoorbeeld query's met slechts één gelijkheids- of bereikfilter). In werkelijkheid hebben de meeste query's veel complexere filterexpressies.
Houd rekening met de volgende query:
SELECT *
FROM company
WHERE company.headquarters.employees = 200 AND CONTAINS(company.headquarters.country, "United")
Als u deze query wilt uitvoeren, moet de query-engine een indexzoekopdracht uitvoeren op en een volledige indexscan uitvoeren op . De query-engine heeft interne heuristieken die worden gebruikt om de queryfilterexpressie zo efficiënt mogelijk te evalueren. In dit geval zou de query-engine voorkomen dat onnodige indexpagina's moeten worden gelezen door eerst de indexzoekfunctie uit te voeren. Als bijvoorbeeld slechts 50 items overeenkomen met het gelijkheidsfilter, hoeft de query-engine alleen te evalueren op de indexpagina's die deze 50 items bevatten. Een volledige indexscan van de hele container is niet nodig.
Indexgebruik voor scalaire statistische functies
Query's met statistische functies moeten uitsluitend afhankelijk zijn van de index om deze te kunnen gebruiken.
In sommige gevallen kan de index fout-positieven retourneren. Wanneer u bijvoorbeeld evalueert op de index, kan het aantal overeenkomsten in de index het aantal queryresultaten overschrijden. De query-engine laadt alle indexovereenkomsten, evalueert het filter op de geladen items en retourneert alleen de juiste resultaten.
Voor de meeste query's heeft het laden van fout-positieve indexovereenkomsten geen merkbaar effect op het indexgebruik.
Kijk bijvoorbeeld eens naar de volgende query:
SELECT *
FROM company
WHERE CONTAINS(company.headquarters.country, "United")
De systeemfunctie kan een aantal fout-positieve matches opleveren, daarom moet de query-engine controleren of elk geladen item overeenkomt met de filterexpressie. In dit voorbeeld hoeft de query-engine mogelijk slechts een paar extra items te laden, zodat het effect op het indexgebruik en de RU-kosten minimaal is.
Query's met statistische functies moeten echter uitsluitend afhankelijk zijn van de index om deze te kunnen gebruiken. Bekijk bijvoorbeeld de volgende query met een aggregatiefunctie:
SELECT COUNT(1)
FROM company
WHERE CONTAINS(company.headquarters.country, "United")
Net als in het eerste voorbeeld retourneert de systeemfunctie mogelijk enkele vals-positieve overeenkomsten. In tegenstelling tot de query kan de query de filterexpressie op de geladen items echter niet evalueren om alle indexovereenkomsten te controleren. De query moet uitsluitend afhankelijk zijn van de index, dus als er een kans is dat een filterexpressie vals-positieve overeenkomsten retourneert, doet de query-engine een volledige scan.
Query's met de volgende statistische functies moeten uitsluitend afhankelijk zijn van de index, dus het evalueren van sommige systeemfuncties vereist een volledige scan.
- AVG
- AANTAL
- MAX
- MIN
- SOM