Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Cosmos DB (i Azure och Fabric) är en schemaagnostisk databas som gör att du kan iterera i ditt program utan att behöva hantera schema- eller indexhantering. Den här funktionen kallas även schema vid läsning, vilket innebär att Cosmos DB inte tillämpar ett schema på dina data när de skrivs till databasen. Schemat definieras i de klasser som du skapar i ditt program när du deserialiserar data från databasen under läs- eller skrivåtgärder.
Indexering i Cosmos DB i Microsoft Fabric är utformat för att leverera snabba och flexibla frågeprestanda, oavsett hur dina data utvecklas. Som standard indexerar Cosmos DB automatiskt varje egenskap för alla objekt i containern utan att behöva definiera något schema eller konfigurera sekundära index.
Konceptuellt träd
Varje gång ett objekt lagras i en container projiceras innehållet som ett JSON-dokument och konverteras sedan till en trädrepresentation. Den här konverteringen innebär att varje egenskap för objektet representeras som en nod i ett träd. En pseudorotnod skapas som överordnad till alla egenskaper på första nivån för objektet. Lövnoderna innehåller de faktiska skalärvärdena som bärs av ett objekt.
Tänk till exempel på det här objektet:
{
"id": "00000000-0000-0000-0000-000000004368",
"name": "Cofaz Jacket",
"tags": [
{ "category": "clothing", "type": "jacket" },
{ "category": "outdoor", "type": "winter" }
],
"inventory": { "warehouse": "Seattle", "quantity": 50 },
"distributors": [
{ "name": "Contoso" },
{ "name": "AdventureWorks" }
]
}
Det här konceptträdet representerar JSON-exempelobjektet:
-
id:00000000-0000-0000-0000-000000004368 -
name:Cofaz Jacket tags0-
category:clothing -
type:jacket
-
1-
category:outdoor -
type:winter
-
inventory-
warehouse:Seattle -
quantity:50
-
distributors0-
name:Contoso
-
1-
name:AdventureWorks
-
Var uppmärksam på hur matriser kodas i trädet: varje post i en matris får en mellanliggande nod märkt med indexet för den posten i matrisen. Den första posten är 0 till exempel och den andra posten är 1.
Egenskapsvägar
Cosmos DB omvandlar objekt till träd eftersom det gör att systemet kan referera till egenskaper med hjälp av deras sökvägar i dessa träd. För att hämta sökvägen för en egenskap kan vi bläddra i trädet från rotnoden till den egenskapen och sammanfoga etiketterna för varje bläddrade nod.
Här är sökvägarna för varje egenskap från exempelobjektet som beskrevs tidigare:
| Väg | Värde |
|---|---|
/id |
"00000000-0000-0000-0000-000000004368" |
/name |
"Cofaz Jacket" |
/tags/0/category |
"clothing" |
/tags/0/type |
"jacket" |
/tags/1/category |
"outdoor" |
/tags/1/type |
"winter" |
/inventory/warehouse |
"Seattle" |
/inventory/quantity |
50 |
/distributors/0/name |
"Contoso" |
/distributors/1/name |
"AdventureWorks" |
Cosmos DB indexerar effektivt varje egenskaps sökväg och dess motsvarande värde när ett objekt skrivs.
Indextyper i Cosmos DB
Cosmos DB stöder för närvarande fyra typer av index.
Du kan konfigurera dessa indextyper när du definierar indexeringsprincipen.
Intervallindex
Intervallindex baseras på en ordnad trädliknande struktur. Intervallindextypen används för:
Likhetsfrågor:
SELECT * FROM container c WHERE c.property = 'value'SELECT * FROM container c WHERE c.property IN ("value1", "value2", "value3")Likhetsmatchning för ett matriselement
SELECT * FROM container c WHERE ARRAY_CONTAINS(c.tags, "tag1")Intervallfrågor:
SELECT * FROM container c WHERE c.property > 0Anmärkning
Fungerar för
>,<,>=, ,<=!=Söker efter förekomsten av en egenskap:
SELECT * FROM container c WHERE IS_DEFINED(c.property)Strängsystemfunktioner:
SELECT * FROM container c WHERE CONTAINS(c.property, "value")SELECT * FROM container c WHERE STRINGEQUALS(c.property, "value")ORDER BYFrågor:SELECT * FROM container c ORDER BY c.propertyJOINFrågor:SELECT d FROM container c JOIN d IN c.properties WHERE d = 'value'
Intervallindex kan användas på skalära värden (sträng eller tal). Standardprincipen för indexering för nyligen skapade containrar framtvingar intervallindex för strängar eller nummer.
Anmärkning
En ORDER BY sats som beställer efter en enskild egenskap behöver alltid ett intervallindex och misslyckas om sökvägen den refererar till inte har något. På samma sätt behöver en ORDER BY fråga som beställer efter flera egenskaper alltid ett sammansatt index.
Rumsligt index
Rumsliga index möjliggör effektiva frågor om geospatiala objekt som punkter, linjer, polygoner och multipolygoner. Dessa frågor använder ST_DISTANCEnyckelorden , ST_WITHIN, ST_INTERSECTS . Följande är några exempel som använder rumslig indextyp:
Geospatiala avståndsfrågor:
SELECT * FROM container c WHERE ST_DISTANCE(c.property, { "type": "Point", "coordinates": [0.0, 10.0] }) < 40Geospatial i frågor:
SELECT * FROM container c WHERE ST_WITHIN(c.property, {"type": "Point", "coordinates": [0.0, 10.0] })Geospatiala korsningsförfrågningar
SELECT * FROM container c WHERE ST_INTERSECTS(c.property, { 'type':'Polygon', 'coordinates': [[ [31.8, -5], [32, -5], [31.8, -5] ]] })
Rumsliga index kan användas på korrekt formaterade GeoJSON-objekt. Punkter, LineStrings, Polygoner och MultiPolygons stöds för närvarande.
Sammansatt index
Sammansatta index ökar effektiviteten när du utför åtgärder på flera fält. Den sammansatta indextypen används för:
ORDER BYfrågor om flera egenskaper:SELECT * FROM container c ORDER BY c.property1, c.property2Frågor med ett filter och
ORDER BY. Dessa frågor kan använda ett sammansatt index om filteregenskapen läggs till iORDER BY-satsen.SELECT * FROM container c WHERE c.property1 = 'value' ORDER BY c.property1, c.property2Frågor med ett filter på två eller flera egenskaper där minst en egenskap är ett likhetsfilter:
SELECT * FROM container c WHERE c.property1 = 'value' AND c.property2 > 'value'
Så länge ett filterpredikat använder en av indextyperna utvärderar frågemotorn det först innan resten genomsöks. Om du till exempel har en SQL-fråga som SELECT * FROM c WHERE c.department = "Information Technology" and CONTAINS(c.team, "Pilot"):
Den här frågan tillämpar först ett filter med hjälp av indexet för poster där
department = "Information Technology". Alla poster idepartment = "Information Technology"skickas sedan genom en efterföljande pipeline för att utvärderaCONTAINSfilterpredikatet.Du kan påskynda frågor och undvika fullständiga containergenomsökningar när du använder funktioner som utför en fullständig genomsökning som
CONTAINS. Du kan lägga till fler filterpredikat som använder indexet för att påskynda dessa frågor. Ordningen på filtersatser är inte viktig. Frågemotorn räknar ut vilka predikat som är mer selektiva och kör frågan därefter.
Vektorindex
Vektorindex ökar effektiviteten när du utför vektorsökningar med hjälp av VECTORDISTANCE systemfunktionen. Vektorsökningar har lägre svarstid, högre dataflöde och mindre RU-förbrukning när du använder ett vektorindex. Cosmos DB stöder alla vektorinbäddningar (text, bild, multimodal osv.) under 4 096 dimensioner i storlek.
ORDER BYvektorsökningsfrågor:SELECT TOP 10 * FROM container c ORDER BY VECTORDISTANCE(c.vector1, c.vector2)Projektion av likhetspoängen i vektorsökningsfrågor:
SELECT TOP 10 c.name, VECTORDISTANCE(c.vector1, c.vector2) AS score FROM container c ORDER BY VECTORDISTANCE(c.vector1, c.vector2)Omfångsfilter för likhetspoäng.
SELECT TOP 10 * FROM container c WHERE VECTORDISTANCE(c.vector1, c.vector2) > 0.8 ORDER BY VECTORDISTANCE(c.vector1, c.vector2)
Viktigt!
Vektorprinciper och vektorindex är oföränderliga när de har skapats. Skapa en ny samling för att göra ändringar.
Så här använder frågor index
Det finns fem sätt som frågemotorn kan utvärdera frågefilter, sorterade efter mest effektiva till minst effektiva:
- Indexsökning
- Exakt indexgenomsökning
- Utökad indexgenomsökning
- Fullständig indexgenomsökning
- Fullständig genomsökning
När du indexerar egenskapssökvägar använder frågemotorn automatiskt indexet så effektivt som möjligt. Förutom att indexera nya egenskapssökvägar behöver du inte konfigurera något för att optimera hur frågor använder indexet. En frågas RU-avgift är en kombination av både RU-avgiften från indexanvändningen och RU-avgiften från inläsning av objekt.
I följande tabell sammanfattas de olika sätt som index används i Cosmos DB:
| Uppslagstyp | Description | Vanliga exempel | Debitering från indexanvändning | Avgifter för inläsning av objekt från transaktionsdatalager |
|---|---|---|---|---|
| Indexsökning | Skrivskyddade obligatoriska indexerade värden och läs endast in matchande objekt från transaktionsdatalagret | Likhetsfilter, IN | Konstant per likhetsfilter | Ökningar baserat på antalet objekt i frågeresultat |
| Exakt indexgenomsökning | Binär sökning efter indexerade värden och läs endast in matchande objekt från transaktionsdatalagret | Intervalljämförelser (>, <, <=eller >=), StartsWith | Jämförbar med indexsökning, ökar något baserat på kardinaliteten för indexerade egenskaper | Ökningar baserat på antalet objekt i frågeresultat |
| Utökad indexgenomsökning | Optimerad sökning (men mindre effektiv än en binär sökning) av indexerade värden och läs endast in matchande objekt från transaktionsdatalagret | StartsWith (skiftlägesokänslig), StringEquals (skiftlägesokänslig) | Ökar något baserat på kardinaliteten för indexerade egenskaper | Ökningar baserat på antalet objekt i frågeresultat |
| Fullständig indexgenomsökning | Läs distinkt uppsättning indexerade värden och läs endast in matchande objekt från transaktionsdatalagret | Contains (Innehåller), EndsWith (Slutar med), RegexMatch (Reguljära uttrycksmatchning), LIKE (LIK) | Ökar linjärt baserat på kardinaliteten för indexerade egenskaper | Ökningar baserat på antalet objekt i frågeresultat |
| Fullständig genomsökning | Läs in alla objekt från transaktionsdatalagret | Övre, nedre | N/A | Ökningar baserat på antalet objekt i containern |
När du skriver frågor bör du använda filterpredikat som använder indexet så effektivt som möjligt. Till exempel, om antingen StartsWith eller Contains skulle fungera för ditt användningsfall, bör du välja StartsWith eftersom det gör en exakt indexgenomsökning i stället för en fullständig indexgenomsökning.
Information om indexanvändning
Tips/Råd
Det här avsnittet beskriver mer information om hur frågor använder index. Den här detaljnivån är inte nödvändig för att lära dig hur du kommer igång med Cosmos DB, men den dokumenteras i detalj för nyfikna användare. Vi refererar till exempelobjektet som delades tidigare i det här dokumentet:
Tänk på följande två exempelobjekt:
[
{
"id": "00000000-0000-0000-0000-000000004368",
"name": "Cofaz Jacket",
"tags": [
{ "category": "clothing", "type": "jacket" },
{ "category": "outdoor", "type": "winter" }
],
"inventory": { "warehouse": "Seattle", "quantity": 50 },
"distributors": [
{ "name": "Contoso" },
{ "name": "AdventureWorks" }
]
},
{
"id": "00000000-0000-0000-0000-000000004002",
"name": "Potana bike",
"tags": [
{ "category": "cycling", "type": "mountain" }
],
"inventory": { "warehouse": "Seattle", "quantity": 30 },
"distributors": [
{ "name": "Contoso" },
{ "name": "Fabrikam" },
{ "name": "Northwind" }
]
}
]
Cosmos DB använder ett inverterat index. Indexet fungerar genom att mappa varje JSON-sökväg till den uppsättning objekt som innehåller det värdet. Objekt-ID-mappningen representeras på många olika indexsidor för containern. Här är ett exempeldiagram över ett inverterat index för en container som innehåller de två exempelobjekten:
| Väg | Värde | Lista över objektidentifierare |
|---|---|---|
/tags/0/category |
clothing |
[00000000-0000-0000-0000-000000004368] |
/tags/0/category |
cycling |
[00000000-0000-0000-0000-000000004002] |
/tags/0/type |
jacket |
[00000000-0000-0000-0000-000000004368] |
/tags/0/type |
mountain |
[00000000-0000-0000-0000-000000004002] |
/tags/1/category |
outdoor |
[00000000-0000-0000-0000-000000004368] |
/tags/1/type |
winter |
[00000000-0000-0000-0000-000000004368] |
/inventory/warehouse |
Seattle |
[00000000-0000-0000-0000-000000004368, 00000000-0000-0000-0000-000000004002] |
/inventory/quantity |
30 |
[00000000-0000-0000-0000-000000004002] |
/inventory/quantity |
50 |
[00000000-0000-0000-0000-0000-000000004001] |
Det inverterade indexet har två viktiga attribut:
För en viss sökväg sorteras värdena i stigande ordning. Därför kan frågemotorn enkelt leverera
ORDER BYfrån indexet.För en viss sökväg kan frågemotorn söka igenom den distinkta uppsättningen möjliga värden för att identifiera indexsidorna där det finns resultat.
Frågemotorn kan använda det inverterade indexet på fyra olika sätt:
Indexsökning
Överväg följande fråga:
SELECT
tag
FROM
tag IN product.tags
WHERE
tag.category = 'outdoor'
Frågepredikatet (filtrering på objekt där en tagg har "utomhus" som kategori) skulle matcha sökvägen som anges här:
tags1-
category:outdoor
-
Eftersom den här frågan har ett likhetsfilter kan vi snabbt identifiera de indexsidor som innehåller frågeresultaten när vi har gått igenom det här trädet. I det här fallet skulle frågemotorn läsa indexsidor som innehåller Objekt 00000000-0000-0000-0000-000000004368. En indexsökning är det mest effektiva sättet att använda indexet. Med en indexsökning läser vi bara de nödvändiga indexsidorna och läser bara in objekten i frågeresultatet. Därför är indexuppslagstiden och RU-avgiften från indexsökningen otroligt låg, oavsett den totala datavolymen.
Exakt indexgenomsökning
Överväg följande fråga:
SELECT
*
FROM
product
WHERE
product.inventory.quantity > 30
Frågepredikatet (filtrering på objekt där det finns fler än 30 enheter i lagret) kan utvärderas med en exakt indexgenomsökning av inventory/quantity sökvägen. När du gör en exakt indexgenomsökning börjar frågemotorn med en binär sökning av den distinkta uppsättningen möjliga värden för att hitta platsen för värdet 30 för inventory/quantity sökvägen. Eftersom värdena för varje sökväg sorteras i stigande ordning är det enkelt för frågemotorn att göra en binär sökning. När frågemotorn har hittat värdet 30börjar den läsa alla återstående indexsidor (i stigande riktning).
Eftersom frågemotorn kan göra en binär sökning för att undvika genomsökning av onödiga indexsidor tenderar exakta indexgenomsökningar att ha jämförbara svarstider och RU-avgifter för indexsökningsåtgärder.
Utökad indexgenomsökning
Överväg följande fråga:
SELECT
*
FROM
product
WHERE
STARTSWITH(product.inventory.warehouse, "Sea", true)
Frågepredikatet (filtrering på objekt som har lager i ett lager som börjar med skiftlägesokänsliga "Sea") kan utvärderas med en utökad indexgenomsökning av inventory/warehouse sökvägen. Åtgärder som utför en utökad indexgenomsökning har optimeringar som kan hjälpa dig att undvika behov av att söka igenom varje indexsida, men som är något dyrare än en exakt indexgenomsöknings binär sökning.
När du till exempel utvärderar skiftlägesokänsligt StartsWith, kontrollerar frågemotorn indexet efter olika möjliga kombinationer av versaler och gemener. Med den här optimeringen kan frågemotorn undvika att läsa de flesta indexsidor. Olika systemfunktioner har olika optimeringar som de kan använda för att undvika att läsa varje indexsida, så de kategoriseras i stort sett som expanderad indexgenomsökning.
Fullständig indexgenomsökning
Överväg följande fråga:
SELECT
*
FROM
product
WHERE
CONTAINS(product.inventory.warehouse, "eat")
Frågepredikatet (filtrering på varor som har ett varulager i ett lagerhus som innehåller "eat") kan utvärderas med en indexgenomsökning av inventory/warehouse sökvägen. Till skillnad från en exakt indexgenomsökning genomsöker en fullständig indexgenomsökning alltid genom den distinkta uppsättningen möjliga värden för att identifiera indexsidorna där det finns resultat. I det här fallet körs CONTAINS på indexet. Indexsökningstiden och RU-avgiften för indexgenomsökningar ökar när sökvägens kardinalitet ökar. Med andra ord, ju fler möjliga distinkta värden som frågemotorn behöver genomsöka, desto högre latens och RU-debitering uppstår vid en fullständig indexgenomsökning.
Överväg till exempel två egenskaper: name och warehouse. Kardinaliteten för namnet är 5 000 och kardinaliteten warehouse är 200. Här är två exempelfrågor som var och en har en CONTAINS systemfunktion som gör en fullständig indexgenomsökning på name egenskapen. Den första frågan använder fler enheter för begäran (RU:er) än den andra frågan eftersom namnets kardinalitet är högre än warehouse.
SELECT
*
FROM
container c
WHERE
CONTAINS(c.name, "Pack", false)
SELECT
*
FROM
c
WHERE
CONTAINS(c.inventory.warehouse, "Sea", false)
Fullständig genomsökning
I vissa fall kanske frågemotorn inte kan utvärdera ett frågefilter med hjälp av indexet. I det här fallet måste frågemotorn läsa in alla objekt från transaktionsarkivet för att kunna utvärdera frågefiltret. Fullständiga genomsökningar använder inte indexet och har en RU-avgift som ökar linjärt med den totala datastorleken. Lyckligtvis är åtgärder som kräver fullständiga genomsökningar sällsynta.
Vektorsökningsfrågor utan ett definierat vektorindex
Om du inte definierar en vektorindexprincip och använder VECTORDISTANCE systemfunktionen i en ORDER BY sats resulterar den här frågan i en fullständig genomsökning och har en RU-avgift som är högre än om du definierade en vektorindexprincip. På liknande sätt, om du använder VECTORDISTANCE med det booleska värdet brute force inställt på sant och inte har ett flat index definierat för vektorsökvägen, så sker en fullständig genomsökning.
Frågor med komplexa filteruttryck
I de tidigare exemplen övervägde vi bara frågor som hade enkla filteruttryck (till exempel frågor med bara ett enda likhets- eller intervallfilter). I verkligheten har de flesta frågor mycket mer komplexa filteruttryck.
Överväg följande fråga:
SELECT
*
FROM
product
WHERE
product.inventory.quantity = 50 AND CONTAINS(product.inventory.warehouse, "Sea")
För att köra den här frågan måste frågemotorn göra en indexsökning på inventory/quantity och en fullständig indexgenomsökning på inventory/warehouse. Frågemotorn har interna heuristiker som används för att utvärdera frågefilteruttrycket så effektivt som möjligt. I det här fallet skulle frågemotorn undvika att behöva läsa onödiga indexsidor genom att göra indexsökningen först. Om till exempel endast 50 objekt matchade likhetsfiltret skulle frågemotorn bara behöva utvärdera CONTAINS på indexsidorna som innehöll dessa 50 objekt. En fullständig indexgenomsökning av hela containern skulle inte vara nödvändig.
Indexanvändning för skalära aggregeringsfunktioner
Frågor med aggregerade funktioner måste uteslutande förlita sig på indexet för att kunna använda det.
I vissa fall kan indexet returnera falska positiva resultat. När du till exempel utvärderar CONTAINS indexet kan antalet matchningar i indexet överskrida antalet frågeresultat. Frågemotorn läser in alla indexmatchningar, utvärderar filtret på de inlästa objekten och returnerar endast rätt resultat.
För de flesta frågor har inläsning av falska positiva indexmatchningar ingen märkbar effekt på indexanvändningen.
Tänk dig följande fråga:
SELECT
*
FROM
product
WHERE
CONTAINS(product.inventory.warehouse, "Sea")
Systemfunktionen CONTAINS kan returnera några falska positiva matchningar, så frågemotorn måste kontrollera om varje inläst objekt matchar filteruttrycket. I det här exemplet kanske frågemotorn bara behöver läsa in ett extra fåtal objekt, så effekten på indexanvändningen och RU-avgiften är minimal.
Frågor med aggregerade funktioner måste dock uteslutande förlita sig på indexet för att kunna använda det. Tänk till exempel på följande fråga med en COUNT aggregering:
SELECT
COUNT(1)
FROM
product
WHERE
CONTAINS(product.inventory.warehouse, "Sea")
Precis som i det första exemplet CONTAINS kan systemfunktionen returnera några falska positiva matchningar. Till skillnad från frågan SELECT * kan frågan dock COUNT inte utvärdera filteruttrycket på de inlästa objekten för att verifiera alla indexmatchningar. Frågan COUNT måste uteslutande förlita sig på indexet, så om det finns en chans att ett filteruttryck returnerar falska positiva matchningar, tillgriper frågemotorn en fullständig genomsökning.
Frågor med följande aggregeringsfunktioner måste endast förlita sig på indexet, så för att utvärdera vissa systemfunktioner krävs en fullständig genomsökning.