Správa indexování ve službě Azure Cosmos DB pro MongoDB

PLATÍ PRO: MongoDB

Azure Cosmos DB pro MongoDB využívá základní funkce správy indexů služby Azure Cosmos DB. Tento článek se zaměřuje na přidání indexů pomocí služby Azure Cosmos DB pro MongoDB. Indexy jsou specializované datové struktury, které dotazují data zhruba o řád rychleji.

Indexování pro server MongoDB verze 3.6 a vyšší

Server Azure Cosmos DB pro MongoDB verze 3.6 nebo novější automaticky indexuje _id pole a klíč horizontálního oddílu (pouze v horizontálně dělených kolekcích). Rozhraní API automaticky vynucuje jedinečnost pole na klíč horizontálního _id oddílu.

Rozhraní API pro MongoDB se chová jinak než ve službě Azure Cosmos DB for NoSQL, které ve výchozím nastavení indexuje všechna pole.

Úprava zásad indexování

Doporučujeme upravit zásady indexování v Průzkumníku dat na webu Azure Portal. V Průzkumníku dat můžete přidat jedno pole a zástupné kóty z editoru zásad indexování:

Editor zásad indexování

Poznámka:

Složené indexy nemůžete vytvářet pomocí editoru zásad indexování v Průzkumníku dat.

Typy indexů

Jedno pole

Indexy můžete vytvořit na libovolném poli. Pořadí řazení indexu s jedním polem nezáleží. Následující příkaz vytvoří index pole name:

db.coll.createIndex({name:1})

Stejný index jednoho pole můžete vytvořit na name webu Azure Portal:

Přidání indexu názvů v editoru zásad indexování

Jeden dotaz používá více indexů s jedním polem, pokud je k dispozici. Pro každou kolekci můžete vytvořit až 500 indexů s jedním polem.

Složené indexy (server MongoDB verze 3.6+)

V rozhraní API pro MongoDB se vyžadují složené indexy, pokud váš dotaz potřebuje možnost řadit na více polích najednou. U dotazů s více filtry, které není potřeba řadit, vytvořte místo složeného indexu více indexů s jedním polem, abyste ušetřili náklady na indexování.

Složený index nebo indexy s jedním polem pro každé pole ve složeného indexu mají stejný výkon pro filtrování v dotazech.

Složené indexy v vnořených polí nejsou ve výchozím nastavení podporovány kvůli omezením polí. Pokud vnořené pole neobsahuje pole, funguje index podle očekávání. Pokud vaše vnořené pole obsahuje pole (kdekoli na cestě), bude tato hodnota v indexu ignorována.

Například složený index obsahující people.dylan.age v tomto případě funguje, protože v cestě není žádné pole:

{
  "people": {
    "dylan": {
      "name": "Dylan",
      "age": "25"
    },
    "reed": {
      "name": "Reed",
      "age": "30"
    }
  }
}

Stejný složený index v tomto případě nefunguje, protože v cestě je pole:

{
  "people": [
    {
      "name": "Dylan",
      "age": "25"
    },
    {
      "name": "Reed",
      "age": "30"
    }
  ]
}

Tuto funkci můžete pro svůj databázový účet povolit povolením funkce EnableUniqueCompoundNestedDocs.

Poznámka:

Složené indexy nelze vytvářet v polích.

Následující příkaz vytvoří složený index polí name a age:

db.coll.createIndex({name:1,age:1})

Složené indexy můžete použít k efektivnímu řazení na více polích najednou, jak je znázorněno v následujícím příkladu:

db.coll.find().sort({name:1,age:1})

Předchozí složený index můžete také použít k efektivnímu řazení dotazu s opačným pořadím řazení u všech polí. Tady je příklad:

db.coll.find().sort({name:-1,age:-1})

Posloupnost cest ve složeného indexu se ale musí přesně shodovat s dotazem. Tady je příklad dotazu, který by vyžadoval další složený index:

db.coll.find().sort({age:1,name:1})

Indexy s více klíči

Azure Cosmos DB vytváří indexy s více klíči pro indexování obsahu uloženého v polích. Pokud indexujete pole s maticovou hodnotou, Azure Cosmos DB automaticky indexuje každý prvek v poli.

Geoprostorové indexy

Mnoho geoprostorových operátorů bude těžit z geoprostorových indexů. Azure Cosmos DB pro MongoDB v současné době podporuje 2dsphere indexy. Rozhraní API zatím nepodporuje 2d indexy.

Tady je příklad vytvoření geoprostorového indexu v location poli:

db.coll.createIndex({ location : "2dsphere" })

Textové indexy

Azure Cosmos DB pro MongoDB v současné době nepodporuje textové indexy. Pro dotazy na vyhledávání textu na řetězce byste měli použít integraci služby Azure AI Search se službou Azure Cosmos DB.

Indexy se zástupnými znaky

Indexy se zástupnými znamény můžete použít k podpoře dotazů na neznámá pole. Představme si, že máte kolekci, která obsahuje data o rodinách.

Tady je část ukázkového dokumentu v této kolekci:

"children": [
   {
     "firstName": "Henriette Thaulow",
     "grade": "5"
   }
]

Tady je další příklad, tentokrát s mírně odlišnou sadou vlastností v children:

"children": [
    {
     "familyName": "Merriam",
     "givenName": "Jesse",
     "pets": [
         { "givenName": "Goofy" },
         { "givenName": "Shadow" }
         ]
   },
   {
     "familyName": "Merriam",
     "givenName": "John",
   }
]

V této kolekci můžou mít dokumenty mnoho různých možných vlastností. Pokud chcete indexovat všechna data v children poli, máte dvě možnosti: vytvořte samostatné indexy pro každou jednotlivou vlastnost nebo vytvořte jeden index se zástupnými znaky pro celé children pole.

Vytvoření indexu se zástupným znakem

Následující příkaz vytvoří index zástupných znaků pro všechny vlastnosti v rámci children:

db.coll.createIndex({"children.$**" : 1})

Na rozdíl od MongoDB můžou indexy se zástupnými cardy podporovat více polí v predikátech dotazů. Pokud místo vytvoření samostatného indexu pro každou vlastnost použijete jeden index se zástupnými znaky, nebude výkon dotazů nijak jiný.

Pomocí syntaxe zástupných znaků můžete vytvořit následující typy indexů:

  • Jedno pole
  • Geoprostorové

Indexování všech vlastností

Tady je postup, jak vytvořit index se zástupným znakem pro všechna pole:

db.coll.createIndex( { "$**" : 1 } )

Indexy se zástupnými znaky můžete vytvořit také pomocí Průzkumníka dat na webu Azure Portal:

Přidání indexu se zástupnými  znaky v editoru zásad indexování

Poznámka:

Pokud právě začínáte s vývojem, důrazně doporučujeme začít se zástupným znakem u všech polí. To může zjednodušit vývoj a usnadnit optimalizaci dotazů.

Dokumenty s mnoha poli můžou mít vysoké poplatky za jednotku žádosti (RU) za zápisy a aktualizace. Pokud tedy máte úlohu s velkým počtem zápisů, měli byste se rozhodnout pro jednotlivé cesty indexování, a ne k použití indexů se zástupnými cardy.

Poznámka:

Podpora jedinečného indexu existujících kolekcí s daty je dostupná ve verzi Preview. Tuto funkci můžete pro svůj databázový účet povolit povolením funkce EnableUniqueIndexReIndex.

Omezení

Indexy se zástupnými čáry nepodporují žádný z následujících typů nebo vlastností indexu:

  • Složená
  • TTL
  • Jedinečný

Na rozdíl od MongoDB nemůžete ve službě Azure Cosmos DB pro MongoDB používat indexy se zástupnými znaky pro:

  • Vytvořit index se zástupnými znaky, který zahrnuje několik konkrétních polí

    db.coll.createIndex(
        { "$**" : 1 },
        { "wildcardProjection " :
            {
               "children.givenName" : 1,
               "children.grade" : 1
            }
        }
    )
    
  • Vytvořit index se zástupnými znaky, který vylučuje několik konkrétních polí

    db.coll.createIndex(
        { "$**" : 1 },
        { "wildcardProjection" :
            {
               "children.givenName" : 0,
               "children.grade" : 0
            }
        }
    )
    

Jako alternativu můžete vytvořit několik indexů se zástupnými znaky.

Vlastnosti indexu

Následující operace jsou běžné pro účty obsluhující protokol wire protocol verze 4.0 a účty obsluhující starší verze. Další informace o podporovaných indexech a indexovaných vlastnostech.

Jedinečné indexy

Jedinečné indexy jsou užitečné pro vynucení, že dva nebo více dokumentů neobsahuje stejnou hodnotu pro indexovaná pole.

Následující příkaz vytvoří jedinečný index pole student_id:

globaldb:PRIMARY> db.coll.createIndex( { "student_id" : 1 }, {unique:true} )
{
    "_t" : "CreateIndexesResponse",
    "ok" : 1,
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 4
}

V případě horizontálně dělených kolekcí musíte zadat klíč horizontálního oddílu (oddílu) pro vytvoření jedinečného indexu. Jinými slovy, všechny jedinečné indexy v horizontálně dělené kolekci jsou složené indexy, kde jedním z polí je klíč horizontálního dělení. Prvním polem v pořadí by měl být klíč horizontálního dělení.

Následující příkazy vytvoří horizontálně dělenou kolekci coll (klíč horizontálního oddílu je university) s jedinečným indexem polí student_id a university:

globaldb:PRIMARY> db.runCommand({shardCollection: db.coll._fullName, key: { university: "hashed"}});
{
    "_t" : "ShardCollectionResponse",
    "ok" : 1,
    "collectionsharded" : "test.coll"
}
globaldb:PRIMARY> db.coll.createIndex( { "university" : 1, "student_id" : 1 }, {unique:true});
{
    "_t" : "CreateIndexesResponse",
    "ok" : 1,
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 3,
    "numIndexesAfter" : 4
}

V předchozím příkladu vynechání "university":1 klauzule vrátí chybu s následující zprávou:

cannot create unique index over {student_id : 1.0} with shard key pattern { university : 1.0 }

Omezení

Jedinečné indexy je potřeba vytvořit, když je kolekce prázdná.

Jedinečné indexy v vnořených polí nejsou ve výchozím nastavení podporovány kvůli omezením polí. Pokud vnořené pole neobsahuje matici, index bude fungovat podle očekávání. Pokud vaše vnořené pole obsahuje pole (kdekoli na cestě), bude tato hodnota ignorována v jedinečném indexu a jedinečnost se pro tuto hodnotu nezachová.

Například jedinečný index pro people.tom.age bude v tomto případě fungovat, protože v cestě není žádné pole:

{ "people": { "tom": { "age": "25" }, "mark": { "age": "30" } } }

ale v tomto případě nebude fungovat, protože v cestě je pole:

{ "people": { "tom": [ { "age": "25" } ], "mark": [ { "age": "30" } ] } }

Tuto funkci můžete pro svůj databázový účet povolit povolením funkce EnableUniqueCompoundNestedDocs.

Indexy TTL

Pokud chcete povolit vypršení platnosti dokumentu v konkrétní kolekci, musíte vytvořit index TTL (Time to Live). Index TTL je index pole _ts s expireAfterSeconds hodnotou.

Příklad:

globaldb:PRIMARY> db.coll.createIndex({"_ts":1}, {expireAfterSeconds: 10})

Předchozí příkaz odstraní všechny dokumenty v db.coll kolekci, které nebyly změněny za posledních 10 sekund.

Poznámka:

Pole _ts je specifické pro službu Azure Cosmos DB a není přístupné z klientů MongoDB. Jedná se o rezervovanou (systémovou) vlastnost, která obsahuje časové razítko poslední úpravy dokumentu.

Sledování průběhu indexu

Verze 3.6 nebo novější služby Azure Cosmos DB pro MongoDB podporuje currentOp() příkaz ke sledování průběhu indexu v instanci databáze. Tento příkaz vrátí dokument, který obsahuje informace o probíhajících operacích v instanci databáze. Pomocí currentOp příkazu můžete sledovat všechny probíhající operace v nativní databázi MongoDB. Ve službě Azure Cosmos DB pro MongoDB tento příkaz podporuje pouze sledování operace indexu.

Tady je několik příkladů, které ukazují, jak pomocí příkazu sledovat průběh indexu currentOp :

  • Získejte průběh indexu pro kolekci:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Získejte průběh indexu pro všechny kolekce v databázi:

    db.currentOp({"command.$db": <databaseName>})
    
  • Získejte průběh indexu pro všechny databáze a kolekce v účtu služby Azure Cosmos DB:

    db.currentOp({"command.createIndexes": { $exists : true } })
    

Příklady výstupu průběhu indexu

Podrobnosti o průběhu indexu zobrazují procento průběhu aktuální operace indexu. Tady je příklad, který ukazuje formát výstupního dokumentu pro různé fáze průběhu indexu:

  • Operace indexu v kolekci "foo" a "bar" databáze, která je dokončena 60 procent, bude mít následující výstupní dokument. Pole Inprog[0].progress.total zobrazuje 100 jako procento dokončení cíle.

    {
          "inprog" : [
          {
                  ………………...
                  "command" : {
                          "createIndexes" : foo
                          "indexes" :[ ],
                          "$db" : bar
                  },
                  "msg" : "Index Build (background) Index Build (background): 60 %",
                  "progress" : {
                          "done" : 60,
                          "total" : 100
                  },
                  …………..…..
          }
          ],
          "ok" : 1
    }
    
  • Pokud se operace indexu právě spustila v kolekci "foo" a "pruhové" databázi, může výstupní dokument zobrazit 0 % průběhu, dokud nedosáhne měřitelné úrovně.

    {
          "inprog" : [
          {
                  ………………...
                  "command" : {
                          "createIndexes" : foo
                          "indexes" :[ ],
                          "$db" : bar
                  },
                  "msg" : "Index Build (background) Index Build (background): 0 %",
                  "progress" : {
                          "done" : 0,
                          "total" : 100
                  },
                  …………..…..
          }
          ],
         "ok" : 1
    }
    
  • Po dokončení probíhající operace indexu se ve výstupním dokumentu zobrazí prázdné inprog operace.

    {
        "inprog" : [],
        "ok" : 1
    }
    

Aktualizace indexu na pozadí

Bez ohledu na hodnotu zadanou pro vlastnost Index pozadí se aktualizace indexu vždy provádějí na pozadí. Vzhledem k tomu, že aktualizace indexu spotřebovávají jednotky žádostí (RU) s nižší prioritou než jiné databázové operace, změny indexu nebudou mít za následek žádné výpadky pro zápisy, aktualizace nebo odstranění.

Při přidávání nového indexu to nemá žádný vliv na dostupnost čtení. Po dokončení transformace indexu budou dotazy využívat pouze nové indexy. Během transformace indexu bude dotazovací modul dál používat existující indexy, takže během transformace indexování budete sledovat podobný výkon čtení, který jste zaznamenali před zahájením změny indexování. Při přidávání nových indexů také neexistuje riziko neúplných nebo nekonzistentních výsledků dotazu.

Při odebírání indexů a okamžitého spouštění dotazů, které mají filtry na vyřazených indexech, můžou být výsledky nekonzistentní a neúplné, dokud se transformace indexu nedokončí. Pokud odeberete indexy, dotazovací modul neposkytuje konzistentní nebo úplné výsledky, když dotazy filtrují tyto nově odebrané indexy. Většina vývojářů indexy neodstraní a pak se je okamžitě pokusí dotazovat, takže v praxi je tato situace nepravděpodobné.

Poznámka:

Průběh indexu můžete sledovat.

Příkaz ReIndex

Příkaz reIndex znovu vytvoří všechny indexy v kolekci. V některých výjimečných případech může být spuštěním reIndex příkazu vyřešen výkon dotazů nebo jiných problémů s indexem v kolekci. Pokud máte problémy s indexováním, doporučujeme znovu vytvořit indexy pomocí reIndex příkazu.

Příkaz můžete spustit reIndex pomocí následující syntaxe:

db.runCommand({ reIndex: <collection> })

Pomocí následující syntaxe můžete zkontrolovat, jestli spuštění příkazu reIndex zlepší výkon dotazů ve vaší kolekci:

db.runCommand({"customAction":"GetCollection",collection:<collection>, showIndexes:true})

Ukázkový výstup:

{
        "database" : "myDB",
        "collection" : "myCollection",
        "provisionedThroughput" : 400,
        "indexes" : [
                {
                        "v" : 1,
                        "key" : {
                                "_id" : 1
                        },
                        "name" : "_id_",
                        "ns" : "myDB.myCollection",
                        "requiresReIndex" : true
                },
                {
                        "v" : 1,
                        "key" : {
                                "b.$**" : 1
                        },
                        "name" : "b.$**_1",
                        "ns" : "myDB.myCollection",
                        "requiresReIndex" : true
                }
        ],
        "ok" : 1
}

Pokud reIndex se zvýší výkon dotazů, bude argument requiresReIndex pravdivý. Pokud reIndex výkon dotazů nezlepšíte, tato vlastnost se vynechá.

Migrace kolekcí s využitím indexů

V současné době můžete vytvořit jedinečné indexy pouze v případě, že kolekce neobsahuje žádné dokumenty. Oblíbené nástroje pro migraci MongoDB se po importu dat pokusí vytvořit jedinečné indexy. Pokud chcete tento problém obejít, můžete místo povolení nástroje pro migraci ručně vytvořit odpovídající kolekce a jedinečné indexy. (Toto chování mongorestore můžete dosáhnout pomocí příznaku --noIndexRestore v příkazovém řádku.)

Indexování pro MongoDB verze 3.2

Dostupné funkce indexování a výchozí hodnoty se liší pro účty Služby Azure Cosmos DB, které jsou kompatibilní s verzí 3.2 přenosového protokolu MongoDB. Můžete zkontrolovat verzi účtu a upgradovat na verzi 3.6.

Pokud používáte verzi 3.2, tato část popisuje klíčové rozdíly ve verzích 3.6 nebo novější.

Vrácení výchozích indexů (verze 3.2)

Na rozdíl od verze 3.6 nebo novější služby Azure Cosmos DB pro MongoDB verze 3.2 indexuje všechny vlastnosti ve výchozím nastavení. Pomocí následujícího příkazu můžete tyto výchozí indexy pro kolekci (coll):

> db.coll.dropIndexes()
{ "_t" : "DropIndexesResponse", "ok" : 1, "nIndexesWas" : 3 }

Po vyřazení výchozích indexů můžete přidat další indexy stejně jako ve verzi 3.6 nebo novější.

Složené indexy (verze 3.2)

Složené indexy obsahují odkazy na více polí dokumentu. Pokud chcete vytvořit složený index, upgradujte na verzi 3.6 nebo 4.0.

Indexy se zástupnými znaky (verze 3.2)

Pokud chcete vytvořit zástupný index, upgradujte na verzi 4.0 nebo 3.6.

Další kroky