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éma-agnosztikus 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ában. A rendszer egy álgyökércsomópontot hoz létre az elem összes első szintű tulajdonságának szülőjeként. 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 példa JSON-elemet jelöli:
Figyelje meg, hogy a tömbök hogyan vannak kódolva a fában: egy tömb minden bejegyzése egy köztes csomópontot kap, amely a tömbben lévő bejegyzés indexével van megjelölve (0, 1 stb.).
Fáktól a tulajdonságútvonalakig
Az Azure Cosmos DB azért alakít át 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.
A korábban ismertetett példaelem minden tulajdonságának elérési útjai:
/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 definiálá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ései:
SELECT * FROM container c WHERE c.property > 'value'
Megjegyzés
(a következőhöz
>
működik: ,<
,>=
,<=
)!=
Tulajdonság meglé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 (sztring vagy szám) 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ával kapcsolatos további információkért lásd: Tartományindexelési szabályzatok példái
Megjegyzés
Egy ORDER BY
olyan záradék, amely egyetlen tulajdonság alapján rendel, mindig szükség van egy tartományindexre, és sikertelen lesz, ha a hivatkozott elérési út nem rendelkezik ilyenrel. Hasonlóképpen, egy ORDER BY
lekérdezésnek, amely több tulajdonsággal rendel, 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öbbpogonon. Ezek a lekérdezések ST_DISTANCE, ST_WITHIN ST_INTERSECTS 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
A lekérdezéseken belüli térinformatika:
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, vonalláncok, sokszögek és multipoligonok jelenleg támogatottak. A térbeli indexek konfigurálásának megismeréséhez lásd: Térbeli indexelési szabályzatok példái
Ö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 aORDER 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 egyik indextípust használja, a lekérdezési motor először kiértékeli, mielőtt beolvasja a többit. 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 azokat a bejegyzéseket szűri, 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 keresztül 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álatokat, ha olyan függvényeket használ, amelyek teljes vizsgálatot végeznek, mint például a CONTAINS. További olyan szűrő-predikátumokat is hozzáadhat, amelyek az indexet használják a lekérdezések felgyorsításához. 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 lásd: Összetett indexelési szabályzatok példái
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 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és kérelemegység-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 | Description | Gyakori példák | RU-díj az indexhasználatból | A tranzakciós adattárból származó elemek betöltésének kérelemegység-díjai |
---|---|---|---|---|
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ó | Növekedés a lekérdezési eredményekben szereplő elemek száma alapján |
Pontos indexvizsgálat | Indexelt értékek bináris keresése és csak az egyező elemek betöltése a tranzakciós adattárból | Tartomány-összehasonlítások (>, , <<= vagy >=), StartsWith | Az indexkereséshez hasonlítható, az indexelt tulajdonságok számossága alapján enyhén nő | Növekedés a lekérdezési eredményekben szereplő elemek száma alapján |
Bővített indexvizsgálat | Indexelt értékek optimalizált keresése (de kevésbé hatékony, mint bináris 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) | Enyhén nő az indexelt tulajdonságok számossága alapján | Növekedés a lekérdezési eredményekben szereplő elemek száma alapján |
Teljes indexvizsgálat | Az indexelt értékek különböző készletének olvasása és csak az egyező elemek betöltése a tranzakciós adattárból | Tartalmazza, EndsWith, RegexMatch, LIKE | Lineáris növekedés az indexelt tulajdonságok számossága alapján | Növekedés a lekérdezési eredményekben szereplő elemek száma alapján |
Teljes vizsgálat | Az összes elem betöltése a tranzakciós adattárból | Felső, Alsó | N/A | Növekedés a tárolóban lévő elemek száma alapján |
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 StartsWith
Contains
működik a használati esetnél, é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 az egyes JSON-elérési utakat az adott értéket tartalmazó elemek készletéhez társítja. Az elemazonosító-megfeleltetés a tároló számos különböző indexlapján jelenik meg. Íme egy mintadiagram egy tároló invertált indexéről, amely a két példaelemet tartalmazza:
Elérési út | Érték | Elemazonosítók listája |
---|---|---|
/locations/0/country | Németország | 1 |
/locations/0/country | Írország | 2 |
/locations/0/city | Berlin | 1 |
/locations/0/city | Dublin | 2 |
/locations/1/country | Franciaország | 1 |
/locations/1/city | Párizs | 1 |
/központ/ország | Belgium | 1, 2 |
/központ/alkalmazottak | 200 | 2 |
/központ/alkalmazottak | 250 | 1 |
Az invertált indexnek két fontos attribútuma van:
- 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ő készletén keresztül vizsgálhatja át azokat az indexlapokat, ahol vannak eredmények.
A lekérdezési motor az invertált indexet négy különböző módon használhatja:
Indexkeresés
Tekintse 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 országa/régiója "Franciaország", megfelel az ábrán kiemelt útvonalnak:
Mivel ez 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ó indexlapokat. 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ényeiben 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
Tekintse 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) kiértékelhető az headquarters/employees
elérési út pontos indexvizsgálatával. 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 200
headquarters/employees
helyét. Mivel az egyes elérési utak értékei növekvő sorrendben vannak rendezve, a lekérdezési motor könnyen elvégezhet bináris keresést. Miután a lekérdezési motor megtalálta az értéket 200
, elkezdi beolvasni az összes többi indexlapot (növekvő irányba haladva).
Mivel a lekérdezési motor bináris keresést végezhet a felesleges indexlapok beolvasásának elkerülése érdekében, a pontos indexvizsgálatok általában hasonló késéssel és ru-díjakkal rendelkeznek az indexkeresési műveletekhez.
Bővített indexvizsgálat
Tekintse meg a következő lekérdezést:
SELECT *
FROM company
WHERE STARTSWITH(company.headquarters.country, "United", true)
A lekérdezési predikátum (a "United" kis- és nagybetűkkel kezdődő helyen található központi elemek szűrése) kiértékelhető az headquarters/country
elérési út kibővített indexvizsgálatával. A kibővített indexvizsgálatot végező műveletek optimalizálása segít elkerülni, hogy minden indexoldalt beolvassunk, de valamivel drágábbak, mint egy pontos indexvizsgálat bináris keresése.
A kis- és nagybetűk megkülönböztetésének kiértékelésekor például a lekérdezési StartsWith
motor ellenőrzi az indexet a kis- és nagybetűk különböző lehetséges kombinációinál. 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 indexlapok olvasását, így széles körben bővített indexvizsgálatként vannak kategorizálva.
Teljes indexvizsgálat
Tekintse 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özponttal rendelkező elemek szűrése headquarters/country
) az elérési út indexvizsgálatával é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ő készletén halad végig, hogy azonosítsa azokat az indexlapokat, ahol vannak eredmények. Ebben az esetben Contains
a rendszer az indexen fut. Az indexkeresési idő és a kérelemegység-díj az indexvizsgálatok esetében 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 megvizsgálnia a lekérdezési motornak, annál nagyobb a késés és a kérelemegység-terhelés a teljes indexvizsgálatban.
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 country
.
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 a tranzakciós tároló összes elemét 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.
Összetett szűrőkifejezéseket tartalmazó lekérdezések
A korábbi példákban csak azokat a lekérdezéseket vettük 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.
Tekintse 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égeznie headquarters/employees
, és teljes indexvizsgálatot kell végeznie a következőn: headquarters/country
. A lekérdezési motor belső heurisztikus elemekkel rendelkezik, amelyeket a lekérdezésszűrő kifejezés lehető leghatékonyabb kiértékeléséhez használ. Ebben az esetben a lekérdezési motornak nem kell elolvasnia a felesleges indexlapokat az indexkeresés első lépésével. Ha például csak 50 elem felel 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ó indexvizsgálatára nincs szükség.
Skaláris összesítő függvények indexkihasználtsága
Az összesítő függvényekkel rendelkező lekérdezések kizárólag 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")
A Contains
rendszerfüggvény téves pozitív találatokat adhat 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 néhány további 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ényekkel rendelkező 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. SELECT *
A lekérdezéstől eltérően 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 találatokat ad vissza, a lekérdezési motor teljes vizsgálatot végez.
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
Az indexelésről az alábbi cikkekben olvashat bővebben: