Megosztás a következőn keresztül:


Az Indexelés áttekintése az Azure Cosmos DB-ben

A KÖVETKEZŐKRE VONATKOZIK: Nosql MongoDB Cassandra Gremlin Táblázat

Az Azure Cosmos DB egy sémafüggetlen adatbázis, amely lehetővé teszi az alkalmazás iterálását anélkül, hogy sémával vagy indexkezeléssel kellene foglalkoznia. Alapértelmezés szerint az Azure Cosmos DB automatikusan indexeli a tároló összes elemének minden tulajdonságát anélkül, hogy sémát kellene definiálnia vagy másodlagos indexeket kellene konfigurálnia.

A cikk célja annak ismertetése, hogy az Azure Cosmos DB hogyan indexeli az adatokat, illetve hogy miként használja az indexeket a lekérdezési teljesítmény javításához. Javasoljuk, hogy az indexelési szabályzatok testreszabása előtt tekintse át ezt a szakaszt.

Elemektől a fákig

Minden alkalommal, amikor egy elem tárolóban van tárolva, annak tartalma JSON-dokumentumként lesz kivetítve, majd faábrázolássá alakul. Ez az átalakítás azt jelenti, hogy az elem minden tulajdonsága csomópontként jelenik meg egy fán. A rendszer egy álgyökércsomópontot hoz létre szülőként az elem összes első szintű tulajdonságához. A levélcsomópontok tartalmazzák az elem által hordozott tényleges skaláris értékeket.

Vegyük például ezt az elemet:

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

Ez a fa a JSON-példaelemet jelöli:

Az előző, faként ábrázolt JSON-elem diagramja.

Figyelje meg, hogy a tömbök hogyan vannak kódolva a fában: egy tömb minden bejegyzése kap egy köztes csomópontot, amely a tömbön belül az adott bejegyzés indexével van megjelölve (0, 1 stb.).

Fáktól a tulajdonságútvonalakig

Az Azure Cosmos DB azért alakítja át az elemeket fákká, mert lehetővé teszi a rendszer számára, hogy a fákon belüli elérési útjukkal hivatkozzon a tulajdonságokra. Egy tulajdonság elérési útjának lekéréséhez a gyökércsomóponttól az adott tulajdonságig bejárhatjuk a fát, és összefűzhetjük az egyes bejárt csomópontok címkéit.

Az egyes tulajdonságok elérési útjai a korábban ismertetett példaelemből származnak:

  • /locations/0/country: "Németország"
  • /locations/0/city: "Berlin"
  • /locations/1/country: "Franciaország"
  • /locations/1/city: "Párizs"
  • /headquarters/country: "Belgium"
  • /headquarters/employees: 250
  • /exports/0/city: "Moszkva"
  • /exports/1/city: "Athén"

Az Azure Cosmos DB hatékonyan indexeli az egyes tulajdonságok elérési útját és annak megfelelő értékét egy elem írásakor.

Indextípusok

Az Azure Cosmos DB jelenleg három indextípust támogat. Ezeket az indextípusokat az indexelési szabályzat meghatározásakor konfigurálhatja.

Tartományindex

A tartományindexek rendezett faszerű szerkezeten alapulnak. A tartományindex típusa a következőhöz használatos:

  • Egyenlőségi lekérdezések:

    SELECT * FROM container c WHERE c.property = 'value'
    
    SELECT * FROM c WHERE c.property IN ("value1", "value2", "value3")
    
  • Egyenlőségegyezés tömbelemen

    SELECT * FROM c WHERE ARRAY_CONTAINS(c.tags, "tag1")
    
  • Tartomány-lekérdezések:

    SELECT * FROM container c WHERE c.property > 'value'
    

    Feljegyzés

    (a , , , >=<=) !=<>

  • Tulajdonság jelenlétének ellenőrzése:

    SELECT * FROM c WHERE IS_DEFINED(c.property)
    
  • Sztringrendszerfüggvények:

    SELECT * FROM c WHERE CONTAINS(c.property, "value")
    
    SELECT * FROM c WHERE STRINGEQUALS(c.property, "value")
    
  • ORDER BY Lekérdezések:

    SELECT * FROM container c ORDER BY c.property
    
  • JOIN Lekérdezések:

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

A tartományindexek skaláris értékeken (sztringen vagy számon) használhatók. Az újonnan létrehozott tárolók alapértelmezett indexelési szabályzata minden sztring vagy szám esetében tartományindexeket kényszerít. A tartományindexek konfigurálásának megismeréséhez tekintse meg a tartományindexelési szabályzat példáit

Feljegyzés

Az ORDER BY egyetlen tulajdonság által megrendelt záradéknak mindig tartományindexre van szüksége, és sikertelen lesz, ha a hivatkozott elérési út nem rendelkezik ilyenrel. Hasonlóképpen, a ORDER BY több tulajdonsággal rendelést tartalmazó lekérdezésnek mindig összetett indexre van szüksége.

Térbeli index

A térinformatikai indexek hatékony lekérdezéseket tesznek lehetővé térinformatikai objektumokon, például pontokon, vonalakon, sokszögeken és többpógonyon. Ezek a lekérdezések ST_DISTANCE, ST_WITHIN, ST_INTER Standard kiadás CTS kulcsszavakat használnak. Az alábbi példák térbeli indextípust használnak:

  • Térinformatikai távolságra vonatkozó lekérdezések:

    SELECT * FROM container c WHERE ST_DISTANCE(c.property, { "type": "Point", "coordinates": [0.0, 10.0] }) < 40
    
  • Térinformatika a lekérdezéseken belül:

    SELECT * FROM container c WHERE ST_WITHIN(c.property, {"type": "Point", "coordinates": [0.0, 10.0] })
    
  • Térinformatikai metszet-lekérdezések:

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

A térbeli indexek megfelelően formázott GeoJSON-objektumokon használhatók. A pontok, a LineStrings, a Sokszögek és a Többpoligonok jelenleg támogatottak. A térbeli indexek konfigurálásának megismeréséhez tekintse meg a térbeli indexelési szabályzat példáit

Összetett indexek

Az összetett indexek növelik a hatékonyságot, ha több mezőn hajt végre műveleteket. Az összetett indextípus a következő célokra használható:

  • ORDER BY lekérdezések több tulajdonságon:

    SELECT * FROM container c ORDER BY c.property1, c.property2
    
  • Lekérdezések szűrővel és ORDER BY. Ezek a lekérdezések összetett indexet használhatnak, ha a szűrőtulajdonság hozzá van adva a ORDER BY záradékhoz.

    SELECT * FROM container c WHERE c.property1 = 'value' ORDER BY c.property1, c.property2
    
  • Két vagy több tulajdonság szűrőjével rendelkező lekérdezések, ahol legalább egy tulajdonság egyenlőségszűrő

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

Ha egy szűrő predikátum az indextípus egyikét használja, a lekérdezési motor ezt először kiértékeli a többi vizsgálat előtt. Ha például sql-lekérdezéssel rendelkezik, például SELECT * FROM c WHERE c.firstName = "Andrew" and CONTAINS(c.lastName, "Liu")

  • A fenti lekérdezés először azokra a bejegyzésekre szűr, ahol a firstName = "Andrew" az index használatával történik. Ezután átadja az összes firstName = "Andrew" bejegyzést egy későbbi folyamaton a CONTAINS szűrő predikátum kiértékeléséhez.

  • Felgyorsíthatja a lekérdezéseket, és elkerülheti a teljes tárolóvizsgálatot, ha olyan függvényeket használ, amelyek teljes vizsgálatot végeznek, például a CONTAINS-t. További szűrő predikátumokat is hozzáadhat, amelyek az index használatával felgyorsítják ezeket a lekérdezéseket. A szűrési záradékok sorrendje nem fontos. A lekérdezési motor kitalálja, hogy mely predikátumok szelektívebbek, és ennek megfelelően futtassa a lekérdezést.

Az összetett indexek konfigurálásának megismeréséhez tekintse meg az összetett indexelési szabályzatra vonatkozó példákat

Vektorindexek

A vektorindexek növelik a hatékonyságot a vektorkeresések rendszerfüggvény használatával VectorDistance történő végrehajtásakor. A vektorkeresések jelentősen alacsonyabb késéssel, nagyobb átviteli sebességgel és kevesebb RU-használattal rendelkeznek a vektorindexek használatakor. A vektorindexek konfigurálásának megismeréséhez tekintse meg a vektorindexelési szabályzat példáit

  • ORDER BY vektorkeresési lekérdezések:

    SELECT c.name
    FROM c
    ORDER BY VectorDistance(c.vector1, c.vector2)
    
  • A vektorkeresési lekérdezések hasonlósági pontszámának előrejelzése:

    SELECT c.name, VectorDistance(c.vector1, c.vector2) AS SimilarityScore
    FROM c
    ORDER BY VectorDistance(c.vector1, c.vector2)
    
  • Tartományszűrők a hasonlósági pontszámon.

    SELECT c.name
    FROM c
    WHERE VectorDistance(c.vector1, c.vector2) > 0.8
    ORDER BY VectorDistance(c.vector1, c.vector2)
    

    Fontos

    A vektorindexeket a tároló létrehozásakor kell meghatározni, és a létrehozás után nem módosíthatók. Egy későbbi kiadásban a vektorindexek módosíthatók lesznek.

Indexhasználat

A lekérdezési motor ötféleképpen értékelheti ki a lekérdezési szűrőket, a leghatékonyabb és a legkevésbé hatékony szerint rendezve:

  • Indexkeresés
  • Pontos indexvizsgálat
  • Bővített indexvizsgálat
  • Teljes indexvizsgálat
  • Teljes vizsgálat

A tulajdonságútvonalak indexelésekor a lekérdezési motor automatikusan a lehető leghatékonyabban használja az indexet. Az új tulajdonságútvonalak indexelése mellett semmit sem kell konfigurálnia az index használatának optimalizálásához. A lekérdezések RU-díja az indexhasználatból származó RU-díj és az elemek betöltéséből származó RU-díj kombinációja.

Az alábbi táblázat összefoglalja az Indexek Azure Cosmos DB-ben való használatát:

Indexkeresés típusa Leírás Gyakori példák RU-díj az indexhasználatból A tranzakciós adattárból származó elemek betöltésekor felmerülő RU-díjak
Indexkeresés Csak a szükséges indexelt értékek olvasása, és csak az egyező elemek betöltése a tranzakciós adattárból Egyenlőségi szűrők, IN Egyenlőségi szűrőnkénti állandó A lekérdezési eredményekben szereplő elemek száma alapján növekszik
Pontos indexvizsgálat Indexelt értékek bináris keresése, és csak a tranzakciós adattárból származó egyező elemek betöltése Tartomány-összehasonlítások (>, <, <= vagy >=), StartsWith Az indexkereséshez hasonló, az indexelt tulajdonságok számossága alapján kissé nő A lekérdezési eredményekben szereplő elemek száma alapján növekszik
Bővített indexvizsgálat Indexelt értékek optimalizált (de bináris keresésnél kevésbé hatékony) keresés, és csak a tranzakciós adattárból származó egyező elemek betöltése StartsWith (kis- és nagybetűk megkülönböztetése), StringEquals (kis- és nagybetűk megkülönböztetése) Az indexelt tulajdonságok számossága alapján kissé nő A lekérdezési eredményekben szereplő elemek száma alapján növekszik
Teljes indexvizsgálat Eltérő indexelt értékek olvasása és csak a tranzakciós adattárból származó egyező elemek betöltése Tartalmazza, EndsWith, RegexMatch, LIKE Lineáris növekedés az indexelt tulajdonságok számossága alapján A lekérdezési eredményekben szereplő elemek száma alapján növekszik
Teljes vizsgálat Az összes elem betöltése a tranzakciós adattárból Felső, Alsó n/a A tárolóban lévő elemek száma alapján növekszik

Lekérdezések írásakor olyan szűrő predikátumokat kell használnia, amelyek a lehető leghatékonyabban használják az indexet. Ha például vagy StartsWithContains a használati esetnél működik, érdemes választania StartsWith , mivel a teljes indexvizsgálat helyett pontos indexvizsgálatot végez.

Indexhasználat részletei

Ebben a szakaszban további részleteket ismertetünk arról, hogyan használják a lekérdezések az indexeket. Ez a részletességi szint nem szükséges az Azure Cosmos DB használatának megkezdéséhez, de a kíváncsi felhasználók számára részletesen dokumentálva van. A dokumentum korábbi részében megosztott példaelemre hivatkozunk:

Példaelemek:

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

Az Azure Cosmos DB fordított indexet használ. Az index úgy működik, hogy megfelelteti az egyes JSON-elérési utakat az adott értéket tartalmazó elemek készletének. Az elemazonosító-megfeleltetés a tároló számos különböző indexlapján jelenik meg. Az alábbi mintadiagram egy olyan tároló invertált indexét mutatja be, amely a két példaelemet tartalmazza:

Elérési út Érték Elemazonosítók listája
/locations/0/country Németország 0
/locations/0/country Írország 2
/locations/0/city Berlin 0
/locations/0/city Dublin 2
/locations/1/country Franciaország 0
/locations/1/city Párizs 0
/székhely/ország Belgium 1, 2
/székhely/alkalmazottak 200 2
/székhely/alkalmazottak 250 0

Az invertált index két fontos attribútummal rendelkezik:

  • Egy adott elérési út esetében az értékek növekvő sorrendben vannak rendezve. Ezért a lekérdezési motor könnyen kiszolgálható ORDER BY az indexből.
  • Egy adott elérési út esetében a lekérdezési motor a lehetséges értékek különböző halmazán keresztül vizsgálhatja azokat az indexlapokat, ahol vannak eredmények.

A lekérdezési motor négy különböző módon tudja használni az invertált indexet:

Indexkeresés

Fontolja meg a következő lekérdezést:

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

A lekérdezési predikátum (olyan elemek szűrése, ahol bármely hely "Franciaország" országként vagy régióként szerepel) megfelelne az ábrán kiemelt útvonalnak:

Egy fa egy adott útvonalának megfelelő bejárási (keresési) diagram.

Mivel a lekérdezés egyenlőségszűrővel rendelkezik, a fa bejárása után gyorsan azonosíthatjuk a lekérdezés eredményeit tartalmazó indexoldalakat. Ebben az esetben a lekérdezési motor felolvassa az 1. elemet tartalmazó indexoldalakat. Az indexkeresés a leghatékonyabb módszer az index használatára. Az indexkereséssel csak a szükséges indexoldalakat olvassuk be, és csak a lekérdezés eredményében szereplő elemeket töltjük be. Ezért az indexkeresési idő és az indexkeresés ru-díja hihetetlenül alacsony, függetlenül a teljes adatmennyiségtől.

Pontos indexvizsgálat

Fontolja meg a következő lekérdezést:

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

A lekérdezési predikátum (a több mint 200 alkalmazottat tartalmazó elemek szűrése) az elérési út pontos indexvizsgálatával headquarters/employees értékelhető ki. A pontos indexvizsgálat során a lekérdezési motor a lehetséges értékek különböző készletének bináris keresésével kezdi meg az elérési út értékének 200headquarters/employees helyét. Mivel az egyes elérési utak értékei növekvő sorrendben vannak rendezve, a lekérdezési motor egyszerűen hajthat végre bináris keresést. Miután a lekérdezési motor megtalálta az értéket 200, megkezdi az összes fennmaradó indexoldal olvasását (növekvő irányban haladva).

Mivel a lekérdezési motor képes bináris keresésre a szükségtelen indexlapok vizsgálatának elkerülése érdekében, a pontos indexvizsgálatok általában hasonló késéssel és ru-díjakkal járnak az indexkeresési műveletekhez.

Bővített indexvizsgálat

Fontolja meg a következő lekérdezést:

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

A lekérdezési predikátum (a kis- és nagybetűket nem megkülönböztető "United" kezdetű helyen lévő, központi helyen lévő elemek szűrése) az elérési út kibővített indexvizsgálatával headquarters/country értékelhető ki. A bővített indexvizsgálatot végező műveletek optimalizálása segít elkerülni, hogy minden indexlapot beolvassunk, de valamivel drágábbak, mint egy pontos indexvizsgálat bináris keresése.

A kis- és nagybetűk érzéketlen StartsWithkiértékelésekor például a lekérdezési motor ellenőrzi az indexet a kis- és nagybetűk különböző lehetséges kombinációihoz. Ez az optimalizálás lehetővé teszi a lekérdezési motor számára, hogy elkerülje a legtöbb indexlap olvasását. A különböző rendszerfüggvények különböző optimalizálásokkal rendelkeznek, amelyekkel elkerülhetik az összes indexlap olvasását, így széles körben kiterjesztett indexvizsgálatként vannak kategorizálva.

Teljes indexvizsgálat

Fontolja meg a következő lekérdezést:

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

A lekérdezési predikátum (a "United" elemet tartalmazó helyen található központi elemekkel rendelkező elemek szűrése az elérési út indexvizsgálatával headquarters/country értékelhető ki. A pontos indexvizsgálattól eltérően a teljes indexvizsgálat mindig a lehetséges értékek különböző halmazán halad végig, hogy azonosítsa azokat az indexoldalakat, ahol vannak eredmények. Ebben az esetben Contains a rendszer az indexen fut. Az indexkeresési idő és az indexvizsgálatok ru-díja az elérési út számosságának növekedésével nő. Más szóval minél több különböző értéket kell a lekérdezési motornak megvizsgálnia, annál nagyobb a késés és a teljes indexvizsgálathoz szükséges ru-díj.

Vegyük például két tulajdonságot: town és country. A város számossága 5000, a számossága country pedig 200. Íme két példa lekérdezés, amelyek mindegyike tartalmaz egy olyan rendszerfüggvényt, amely teljes indexvizsgálatot végez a town tulajdonságon. Az első lekérdezés több kérelemegységet használ, mint a második lekérdezés, mert a város számossága magasabb, mint countrya .

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

Teljes vizsgálat

Bizonyos esetekben előfordulhat, hogy a lekérdezési motor nem tudja kiértékelni a lekérdezésszűrőt az index használatával. Ebben az esetben a lekérdezési motornak be kell töltenie az összes elemet a tranzakciós tárolóból a lekérdezésszűrő kiértékeléséhez. A teljes vizsgálat nem használja az indexet, és a teljes adatmérettel lineárisan növekvő RU-díjjal rendelkezik. Szerencsére a teljes vizsgálatot igénylő műveletek ritkák.

Vektorkeresési lekérdezések definiált vektorindex nélkül

Ha nem határoz meg vektorindex-szabályzatot, és a VectorDistance rendszerfüggvényt egy ORDER BY záradékban használja, akkor ez teljes vizsgálathoz vezet, és ru-díj magasabb lesz, mint ha vektorindex-szabályzatot definiált. Hasonlóság, ha a VectorDistance függvényt a találgatásos logikai értékre állítja true, és nincs flat definiálva index a vektor elérési útjának, akkor teljes vizsgálatra kerül sor.

Összetett szűrőkifejezéseket tartalmazó lekérdezések

A korábbi példákban csak olyan lekérdezéseket vettünk figyelembe, amelyek egyszerű szűrőkifejezésekkel rendelkeztek (például egyetlen egyenlőség- vagy tartományszűrővel rendelkező lekérdezések). A valóságban a legtöbb lekérdezés sokkal összetettebb szűrőkifejezésekkel rendelkezik.

Fontolja meg a következő lekérdezést:

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

A lekérdezés végrehajtásához a lekérdezési motornak indexkeresést kell végeznieheadquarters/employees, és teljes indexvizsgálatot kell végeznie.headquarters/country A lekérdezési motor belső heurisztikusokkal rendelkezik, amelyekkel a lekérdezésszűrő kifejezés a lehető leghatékonyabban kiértékelhető. Ebben az esetben a lekérdezési motornak nem kell elolvasnia a szükségtelen indexoldalakat az indexkeresés első lépésével. Ha például csak 50 elem felelt meg az egyenlőségi szűrőnek, a lekérdezési motornak csak az 50 elemet tartalmazó indexlapokon kell kiértékelnie Contains . A teljes tároló teljes indexvizsgálatára nincs szükség.

Skaláris összesítő függvények indexkihasználtsága

Az aggregátumfüggvényeket tartalmazó lekérdezések csak az indexre támaszkodhatnak a használatukhoz.

Bizonyos esetekben az index hamis pozitív értékeket adhat vissza. Az index kiértékelésekor Contains például az indexben lévő egyezések száma meghaladhatja a lekérdezési eredmények számát. A lekérdezési motor betölti az összes index egyezést, kiértékeli a szűrőt a betöltött elemeken, és csak a megfelelő eredményeket adja vissza.

A legtöbb lekérdezés esetében a hamis pozitív index-egyezések betöltése nem befolyásolja az index kihasználtságát.

Lásd példaként az alábbi lekérdezést:

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

Előfordulhat, hogy a Contains rendszerfüggvény hamis pozitív egyezéseket ad vissza, ezért a lekérdezési motornak ellenőriznie kell, hogy minden betöltött elem megfelel-e a szűrőkifejezésnek. Ebben a példában előfordulhat, hogy a lekérdezési motornak csak további néhány elemet kell betöltenie, így az index kihasználtságára és a kérelemegység-terhelésre gyakorolt hatás minimális.

Az aggregátumfüggvényeket tartalmazó lekérdezések azonban kizárólag az indexre támaszkodhatnak a használatukhoz. Vegyük például a következő lekérdezést összesítéssel Count :

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

Az első példához hasonlóan a Contains rendszerfüggvény is visszaadhat néhány hamis pozitív egyezést. A SELECT * lekérdezéssel ellentétben azonban a Count lekérdezés nem tudja kiértékelni a betöltött elemek szűrőkifejezését az összes index egyezésének ellenőrzéséhez. A Count lekérdezésnek kizárólag az indexre kell támaszkodnia, így ha van rá esély, hogy egy szűrőkifejezés hamis pozitív egyezéseket ad vissza, a lekérdezési motor teljes vizsgálathoz folyamodik.

Az alábbi összesítő függvényekkel rendelkező lekérdezések kizárólag az indexre támaszkodhatnak, ezért egyes rendszerfüggvények kiértékeléséhez teljes vizsgálatra van szükség.

Következő lépések

További információ az indexelésről az alábbi cikkekben: