Sdílet prostřednictvím


Indexování ve službě Cosmos DB v Microsoft Fabric

Cosmos DB je databáze nezávislá na schématu, která umožňuje iterovat ve vaší aplikaci bez nutnosti zabývat se správou schématu nebo indexu. To se také označuje jako schéma při čtení, což znamená, že Cosmos DB při zápisu do databáze nevynucuje schéma dat. Místo toho se schéma promítá do tříd, které v aplikaci definujete při deserializaci dat z databáze při čtení nebo dotazování dat.

Indexování ve službě Cosmos DB v Microsoft Fabric je navržené tak, aby poskytovalo rychlý a flexibilní výkon dotazů bez ohledu na to, jak se vaše data vyvíjejí. Cosmos DB ve výchozím nastavení automaticky indexuje všechny vlastnosti všech položek v kontejneru, aniž by bylo nutné definovat jakékoli schéma nebo konfigurovat sekundární indexy.

Koncepční strom

Pokaždé, když je položka uložená v kontejneru, její obsah se promítá jako dokument JSON a pak se převede na reprezentaci stromu. Tento převod znamená, že každá vlastnost této položky je reprezentována jako uzel ve stromu. Pseudo kořenový uzel je vytvořen jako rodičový uzel pro všechny vlastnosti na první úrovni položky. Uzly typu list obsahují skutečné skalární hodnoty přenášené položkou.

Jako příklad zvažte tuto položku:

{
  "locations": [
    { 
      "country": "Germany", 
      "city": "Berlin" 
    },
    { 
      "country": "France", 
      "city": "Paris" 
    }
  ],
  "headquarters": { 
    "country": "Belgium", 
    "employees": 250 
  },
  "exports": [
    { 
      "city": "Moscow" 
    },
    { 
      "city": "Athens" 
    }
  ]
}

Tento koncepční strom představuje ukázkovou položku JSON:

  • locations
    • 0
      • country: Germany
      • city: Berlin
    • 1
      • country: France
      • city: Paris
  • headquarters
    • country: Belgium
    • employees: 250
  • exports
    • 0
      • city: Moscow
    • 1
      • city: Athens

Diagram stromové reprezentace položky ve službě Cosmos DB

Stromový diagram znázorňující kořenový uzel se třemi větvemi: "umístění", "ústředí" a "exporty". Umístění se dělí na dva číslované uzly, z nichž každý má dva dílčí uzly týkající se umístění ("Německo nebo Berlín" a "Francie nebo Paříž"). "Sídlo se nachází v Belgii a má 250 zaměstnanců." "Exporty" se dělí na dva číslovaný uzly, z nichž každý má dílčí uzel "město" ("Moskva" a "Atény").

Věnujte pozornost tomu, jak jsou pole zakódována ve stromu: každá položka v poli získá zprostředkující uzel označený indexem této položky v rámci pole. Například první položka je 0 a druhá položka je 1.

Cesty k vlastnostem

Cosmos DB transformuje položky na stromy, protože umožňuje systému odkazovat na vlastnosti pomocí jejich cest v těchto stromech. Abychom získali cestu k vlastnosti, můžeme procházet strom od kořenového uzlu k této vlastnosti a shromáždit popisky jednotlivých procházených uzlů.

Tady jsou cesty pro každou vlastnost z ukázkové položky popsané výše:

Cesta Hodnota
/locations/0/country "Germany"
/locations/0/city "Berlin"
/locations/1/country "France"
/locations/1/city "Paris"
/headquarters/country "Belgium"
/headquarters/employees 250
/exports/0/city "Moscow"
/exports/1/city "Athens"

Cosmos DB efektivně indexuje cestu každé vlastnosti a její odpovídající hodnotu při zápisu položky.

Typy indexů

Cosmos DB v současné době podporuje čtyři typy indexů.

Tyto typy indexů můžete nakonfigurovat při definování zásad indexování.

Index rozsahu

Indexy rozsahu jsou založené na uspořádané stromové struktuře. Toto je výchozí typ indexu a při definování zásad indexu není nutné zadávat. Typ indexu rozsahu se používá pro:

  • Dotazy na rovnost:

    SELECT
      *
    FROM
      container c
    WHERE
      c.property = 'value'
    
    SELECT
      *
    FROM
      container c
    WHERE
      c.property IN ("value1", "value2", "value3")
    
  • Srovnání rovnosti u prvku pole

    SELECT
      *
    FROM
      container c
    WHERE
      ARRAY_CONTAINS(c.tags, "tag1")
    
  • Dotazy na rozsah:

    SELECT
      *
    FROM
      container c
    WHERE
      c.property > 0
    

    Poznámka:

    Pracuje pro >, <, >=, <=!=

  • Kontrola přítomnosti vlastnosti:

    SELECT
      *
    FROM
      container c
    WHERE
      IS_DEFINED(c.property)
    
  • Funkce systému řetězců:

    SELECT
      *
    FROM
      container c
    WHERE
      CONTAINS(c.property, "value")
    
    SELECT
      *
    FROM
      container c
    WHERE
      STRINGEQUALS(c.property, "value")
    
  • ORDER BY dotazy:

    SELECT
      *
    FROM
      container c
    ORDER BY
      c.property
    
  • JOIN dotazy:

    SELECT
      d
    FROM
      container c
    JOIN
      d IN c.properties
    WHERE
      d = 'value'
    

Indexy rozsahu lze použít u skalárních hodnot (řetězec nebo číslo). Výchozí zásady indexování pro nově vytvořené kontejnery u všech řetězců a čísel vynucují indexy rozsahu.

Poznámka:

ORDER BY Klauzule, která řadí podle jediné vlastnosti, vždy potřebuje index funkční oblasti a selže, pokud cesta, na kterou odkazuje, jeden nemá. Podobně dotaz ORDER BY, který seřazuje podle více vlastností , vždy potřebuje složený index.

Prostorový index

Prostorové indexy umožňují efektivní dotazy na geoprostorové objekty, jako jsou body, čáry, mnohoúhelníky a multipolygony. Tyto dotazy používají ST_DISTANCEklíčová slova , ST_WITHIN. ST_INTERSECTS Tady je několik příkladů, které používají typ prostorového indexu:

  • Geoprostorové dotazy na vzdálenost:

    SELECT
      *
    FROM
      container c
    WHERE
      ST_DISTANCE(c.property, { "type": "Point", "coordinates": [0.0, 10.0] }) < 40
    
  • Geoprostorové v dotazech:

    SELECT
      *
    FROM
      container c
    WHERE
      ST_WITHIN(c.property, {"type": "Point", "coordinates": [0.0, 10.0] })
    
  • Geoprostorové protínající dotazy:

    SELECT
      *
    FROM
      container c
    WHERE
      ST_INTERSECTS(c.property, { 'type':'Polygon', 'coordinates': [[ [31.8, -5], [32, -5], [31.8, -5] ]]  })  
    

Prostorové indexy lze použít pro správně formátované objekty GeoJSON . Body, LineStrings, Polygons a MultiPolygons jsou v současné době podporovány.

Složený index

Složené indexy zvyšují efektivitu při provádění operací s více poli. Složený typ indexu se používá pro:

  • ORDER BY dotazy na více vlastností:

    SELECT
      *
    FROM
      container c
    ORDER BY
      c.property1,
      c.property2
    
  • Dotazy s filtrem a ORDER BY. Tyto dotazy mohou využít složený index, pokud je vlastnost filtru přidána ORDER BY do klauzule.

    SELECT
      *
    FROM
      container c
    WHERE
      c.property1 = 'value'
    ORDER BY
      c.property1,
      c.property2
    
  • Dotazy s filtrem na dvě nebo více vlastností, kde alespoň jedna vlastnost je filtr rovnosti:

    SELECT
      *
    FROM
      container c
    WHERE
      c.property1 = 'value' AND
      c.property2 > 'value'
    

Pokud některý predikát filtru používá některý z typů indexů, dotazovací modul nejprve vyhodnotí tento predikát před prohledáním zbytku. Pokud máte například dotaz SQL, například SELECT * FROM c WHERE c.department = "Information Technology" and CONTAINS(c.team, "Pilot"):

  • Tento dotaz nejprve použije filtr pomocí indexu pro položky, kde department = "Information Technology". Pak převede všechny položky department = "Information Technology" prostřednictvím dalšího kanálu pro vyhodnocení predikátu filtru CONTAINS.

  • Dotazy můžete urychlit a vyhnout se úplným kontrolám kontejnerů při použití funkcí, které provádějí úplnou kontrolu, jako je CONTAINS. Můžete přidat další predikáty filtru, které používají index k urychlení těchto dotazů. Pořadí klauzulí filtru není důležité. Dotazovací modul zjistí, které predikáty jsou selektivnější, a odpovídajícím způsobem dotaz spustí.

Vektorový index

Vektorové indexy zvyšují efektivitu při provádění vektorových hledání pomocí VECTORDISTANCE systémové funkce. Při použití vektorového indexu mají hledání vektorů nižší latenci, vyšší propustnost a nižší spotřebu RU. Cosmos DB podporuje jakékoli vektorové vkládání (text, obrázek, multimodální atd.) pod velikostí 4 096.

  • ORDER BY vektorové vyhledávací dotazy:

    SELECT TOP 10
      *
    FROM
      container c
    ORDER BY
      VECTORDISTANCE(c.vector1, c.vector2)
    
  • Projekce skóre podobnosti v dotazech vektorového vyhledávání:

    SELECT TOP 10
      c.name,
      VECTORDISTANCE(c.vector1, c.vector2) AS score
    FROM
      container c
    ORDER BY
      VECTORDISTANCE(c.vector1, c.vector2)
    
  • Filtry rozsahu podle skóre podobnosti.

    SELECT TOP 10
      *
    FROM
      container c
    WHERE
      VECTORDISTANCE(c.vector1, c.vector2) > 0.8
    ORDER BY
      VECTORDISTANCE(c.vector1, c.vector2)
    

Důležité

Zásady vektoru a indexy vektorů jsou po vytvoření neměnné. Pokud chcete provést změny, vytvořte novou kolekci.

Využití indexu

Dotazovací modul může vyhodnotit filtry dotazů seřazené podle nejúčinnějších a nejméně efektivních způsobů:

  • Vyhledávání pomocí indexu
  • Přesné prohledávání indexu
  • Rozšířené prohledávání indexu
  • Úplná kontrola indexu
  • Úplná kontrola

Když indexujete cesty vlastností, dotazovací modul index automaticky použije co nejefektivněji. Kromě indexování nových cest vlastností nemusíte nic konfigurovat, abyste optimalizovali způsob, jakým dotazy používají index. Poplatek za RU dotazu je součtem poplatku za RU při využití indexu a poplatku za RU při načítání položek.

Následující tabulka shrnuje různé způsoby použití indexů ve službě Cosmos DB:

Typ Lookup Popis Běžné příklady Poplatek z využití indexu Poplatky za načítání položek z transakčního úložiště dat
Hledání indexu Čtení povinných indexovaných hodnot a načtení pouze odpovídajících položek z transakčního úložiště dat Filtry rovnosti, IN Filtr podle rovnosti konstant Zvyšuje se na základě počtu položek ve výsledcích dotazu.
Přesná kontrola indexu Binární vyhledávání indexovaných hodnot a načítání pouze odpovídajících položek z transakčního úložiště dat Porovnání rozsahů (>, <, <=, nebo >=), začíná s Srovnatelné s vyhledáváním v indexu se mírně zvyšuje na základě kardinality indexovaných vlastností. Zvyšuje se na základě počtu položek ve výsledcích dotazu.
Rozšířené prohledávání indexu Optimalizované vyhledávání (ale méně efektivní než binární vyhledávání) indexovaných hodnot a načítání pouze odpovídajících položek z transakčního úložiště dat StartsWith (nerozlišující velká a malá písmena), StringEquals (nerozlišuje velká a malá písmena) Mírně se zvyšuje na základě kardinality indexovaných vlastností. Zvyšuje se na základě počtu položek ve výsledcích dotazu.
Úplná kontrola indexu Čtení jedinečné sady indexovaných hodnot a načtení pouze odpovídajících položek z transakčního úložiště dat Obsahuje, EndsWith, RegexMatch, LIKE Lineárně se zvyšuje na základě kardinality indexovaných vlastností. Zvyšuje se na základě počtu položek ve výsledcích dotazu.
úplné skenování Načtení všech položek z transakčního úložiště dat Horní, Dolní není k dispozici Zvyšuje se na základě počtu položek v kontejneru.

Při psaní dotazů byste měli použít predikáty filtru, které index používají co nejefektivněji. Pokud by pro váš případ použití mohlo fungovat jak StartsWith, tak i Contains, měli byste se rozhodnout pro StartsWith, protože provádí přesnou kontrolu indexu namísto úplné.

Podrobnosti o využití indexu

Návod

Tato část obsahuje další podrobnosti o tom, jak dotazy používají indexy. Tato úroveň podrobností není nutná k tomu, abyste se naučili, jak začít pracovat se službou Cosmos DB, ale je podrobně zdokumentovaná pro zvědavé uživatele. Odkazujeme na ukázku položky sdílené dříve v tomto dokumentu:

Vezměte v úvahu tyto dvě ukázkové položky:

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

Cosmos DB používá invertovaný index. Index funguje tak, že namapuje každou cestu JSON na sadu položek, které danou hodnotu obsahují. Mapování ID položky je reprezentováno na mnoha různých stránkách indexu kontejneru. Tady je ukázkový diagram invertovaného indexu pro kontejner, který obsahuje dvě ukázkové položky:

Cesta Hodnota Seznam identifikátorů položek
/locations/0/country Germany [1]
/locations/0/country Ireland [2]
/locations/0/city Berlin [1]
/locations/0/city Dublin [2]
/locations/1/country France [1]
/locations/1/city Paris [1]
/headquarters/country Belgium [1, 2]
/headquarters/employees 200 [2]
/headquarters/employees 250 [1]

Invertovaný index má dva důležité atributy:

  • Pro danou cestu jsou hodnoty seřazeny vzestupně. Proto může vyhledávací modul snadno poskytovat ORDER BY z indexu.

  • Pro danou cestu může dotazovací modul prohledávat odlišnou sadu možných hodnot a identifikovat stránky indexu, ve kterých jsou výsledky.

Dotazovací stroj může invertovaný index využívat čtyřmi různými způsoby:

Vyhledávání pomocí indexu

Představte si následující dotaz:

SELECT
  location
FROM
  location IN company.locations
WHERE
  location.country = 'France'

Predikát dotazu (filtrování položek, kde má libovolné umístění jako oblast 'Francii') by odpovídal zde uvedené cestě:

  • locations
    • 1
      • country: France

Diagram procházení (vyhledávání) odpovídající určité cestě ve stromové reprezentaci položky ve službě Cosmos DB

Stromový diagram znázorňující kořenový uzel se třemi větvemi: "umístění", "ústředí" a "exporty". Umístění se dělí na dva číslované uzly, z nichž každý má dva dílčí uzly související s umístěním (Německo/Berlín a Francie/Paříž). "Sídlo se nachází v Belgii a má 250 zaměstnanců." "Exporty" se dělí na dva číslovaný uzly, z nichž každý má dílčí uzel "město" ("Moskva" a "Atény"). Zvýrazní se cesta pro "umístění", "1", umístění a "Francie".

Vzhledem k tomu, že tento dotaz má filtr rovnosti, můžeme po procházení tohoto stromu rychle identifikovat indexové stránky, které obsahují výsledky dotazu. V tomto případě by dotazovací modul četl indexové stránky, které obsahují položku 1. Hledání indexu je nejúčinnější způsob použití indexu. Při hledání indexu čteme pouze potřebné indexové stránky a načítáme pouze položky ve výsledcích dotazu. Proto je doba vyhledávání indexu a poplatky za RU z vyhledávání indexu neuvěřitelně nízké bez ohledu na celkový objem dat.

Přesné prohledávání indexu

Představte si následující dotaz:

SELECT
  *
FROM
  company
WHERE
  company.headquarters.employees > 200

Predikát dotazu (filtrování položek, u kterých je více než 200 zaměstnanců), je možné vyhodnotit přesným prohledáváním indexu headquarters/employees cesty. Když provádíte přesné skenování indexu, dotazovací stroj začne binárním vyhledáváním jedinečné sady možných hodnot k nalezení umístění hodnoty 200 pro cestu headquarters/employees. Vzhledem k tomu, že hodnoty pro každou cestu jsou seřazené vzestupně, je snadné, aby dotazovací modul udělal binární vyhledávání. Jakmile dotazovací modul najde hodnotu 200, začne číst všechny zbývající indexové stránky (ve vzestupném směru).

Vzhledem k tomu, že dotazovací modul může provádět binární vyhledávání, aby se zabránilo prohledávání nepotřebných indexových stránek, bývá latence a poplatky RU při přesném prohledávání indexů srovnatelné s operacemi vyhledávání indexů.

Rozšířené prohledávání indexu

Představte si následující dotaz:

SELECT
  *
FROM
  company
WHERE
  STARTSWITH(company.headquarters.country, "United", true)

Predikát dotazu (filtrování položek, které mají ústředí na místě začínajícím nezávisle na velikosti písmen "United") lze vyhodnotit pomocí rozšířeného prohledávání indexu na cestě headquarters/country. Operace, které provádějí rozšířený průchod indexem, mají optimalizace, které vám můžou pomoct vyhnout se prohledávání každé stránky indexu, ale jsou o něco dražší než přesné binární vyhledávání v indexu.

Například při vyhodnocování nerozlišující malá StartsWitha velká písmena dotazovací modul zkontroluje index pro různé možné kombinace velkých a malých písmen. Tato optimalizace umožňuje dotazovacímu stroji zabránit čtení většiny indexových stránek. Různé systémové funkce mají různé optimalizace, které můžou použít, aby se zabránilo čtení každé indexové stránky, takže jsou široce kategorizovány jako rozšířené prohledávání indexu.

Úplná kontrola indexu

Představte si následující dotaz:

SELECT
  *
FROM
  company
WHERE
  CONTAINS(company.headquarters.country, "United")

Predikát dotazu (filtrování položek, které mají ústředí v umístění, které obsahuje "United") je možné vyhodnotit pomocí prohledávání cesty indexem headquarters/country . Na rozdíl od přesného prohledávání indexu prohledává úplná kontrola indexu vždy odlišnou sadu možných hodnot, aby identifikovala stránky indexu, ve kterých jsou výsledky. V tomto případě se CONTAINS spustí na indexu. Doba vyhledávání v indexu a výpočetní náklady spojené s průchodem indexu se zvyšují s rostoucí kardinalitou cesty. Jinými slovy, čím více možných unikátních hodnot musí dotazovací stroj prohledávat, tím vyšší je latence a náklady RU spojené s prováděním úplného prohledání indexu.

Představte si například dvě vlastnosti: town a country. Kardinalita města je 5 000 a kardinalita country je 200. Tady jsou dva příklady dotazů, které mají každou systémovou CONTAINS funkci, která provede úplnou kontrolu indexu u town vlastnosti. První dotaz používá více jednotek žádostí než druhý dotaz, protože kardinalita města je vyšší než country.

SELECT
  *
FROM
  container c
WHERE
 CONTAINS(c.town, "Red", false)
SELECT
  *
FROM
  c
WHERE
  CONTAINS(c.country, "States", false)

Úplná kontrola

V některých případech nemusí být dotazovací modul schopen vyhodnotit filtr dotazu pomocí indexu. V tomto případě musí dotazovací modul načíst všechny položky z transakčního úložiště, aby se vyhodnotil filtr dotazu. Úplné kontroly nepoužívají index a mají poplatky za RU, které se lineárně zvyšují s celkovou velikostí dat. Operace vyžadující úplné kontroly jsou naštěstí vzácné.

Vektorové vyhledávací dotazy bez definovaného vektorového indexu

Pokud nedefinujete zásadu indexu vektoru a použijete systémovou funkci VECTORDISTANCE v klauzuli ORDER BY, pak tento dotaz povede k úplné kontrole a výsledkem bude vyšší poplatek za RU, než kdybyste definovali zásadu indexu vektoru. Podobně, pokud použijete VECTORDISTANCE s hrubou silou prologickou hodnotu nastavenou na true a nemáte definovaný flat index pro cestu vektoru, dojde k úplnému skenování.

Dotazy s komplexními výrazy filtru

V předchozích příkladech jsme považovali pouze dotazy, které obsahovaly jednoduché výrazy filtru (například dotazy s pouze jedním filtrem rovnosti nebo rozsahu). Ve skutečnosti má většina dotazů mnohem složitější výrazy filtru.

Představte si následující dotaz:

SELECT
  *
FROM
  company
WHERE
  company.headquarters.employees = 200 AND CONTAINS(company.headquarters.country, "United")

Chcete-li tento dotaz spustit, musí dotazovací modul provést vyhledávání v indexu na headquarters/employees a úplné prohledání indexu na headquarters/country. Dotazovací modul má interní heuristiku, kterou používá k co nejefektivnějšímu vyhodnocení výrazu filtru dotazu. V takovém případě by dotazovací modul nemusel číst nepotřebné indexové stránky tím, že nejprve hledá index. Pokud by například filtr rovnosti splňoval pouze 50 položek, dotazovací modul by musel vyhodnotit CONTAINS jenom na stránkách indexu, které obsahovaly těchto 50 položek. Úplná kontrola indexu celého kontejneru by nebyla nutná.

Využití indexu pro skalární agregační funkce

Dotazy s agregačními funkcemi musí záviset výhradně na indexu, aby je bylo možné použít.

V některých případech může index vrátit falešně pozitivní výsledky. Například při vyhodnocování CONTAINS indexu může počet shod v indexu překročit počet výsledků dotazu. Dotazovací modul načte všechny shody indexů, vyhodnotí filtr načtených položek a vrátí pouze správné výsledky.

U většiny dotazů nemá načítání falešně pozitivních indexů žádný znatelný vliv na využití indexu.

Zvažte například následující dotaz:

SELECT
  *
FROM
  company
WHERE
  CONTAINS(company.headquarters.country, "United")

Systémová CONTAINS funkce může vrátit některé falešně pozitivní shody, takže dotazovací modul musí ověřit, zda každá načtená položka odpovídá výrazu filtru. V tomto příkladu může dotazovací modul načíst ještě pouze několik dalších položek, takže vliv na využití indexu a poplatky za RU je minimální.

Dotazy s agregačními funkcemi se ale musí spoléhat výhradně na index, aby je bylo možné použít. Představte si například následující dotaz s agregací COUNT :

SELECT
  COUNT(1)
FROM
  company
WHERE
  CONTAINS(company.headquarters.country, "United")

Stejně jako v prvním příkladu může systémová funkce CONTAINS vrátit některé falešně pozitivní shody. Na rozdíl od dotazu SELECT * ale dotaz COUNT nemůže vyhodnotit výraz filtru u načtených položek, aby ověřil všechny shody indexu. Dotaz COUNT se musí spoléhat výhradně na index, takže pokud existuje šance, že výraz filtru vrátí false positives, dotazovací stroj se uchýlí k úplnému prohledávání.

Dotazy s následujícími agregačními funkcemi musí záviset výhradně na indexu, takže vyhodnocení některých systémových funkcí vyžaduje úplnou kontrolu.