Hantera indexering i Azure Cosmos DB för MongoDB

GÄLLER FÖR: Mongodb

Azure Cosmos DB for MongoDB drar nytta av de viktigaste funktionerna för indexhantering i Azure Cosmos DB. Den här artikeln fokuserar på hur du lägger till index med Hjälp av Azure Cosmos DB för MongoDB. Index är specialiserade datastrukturer som gör det ungefär snabbare att köra frågor mot dina data.

Indexering för MongoDB-server version 3.6 och senare

Azure Cosmos DB för MongoDB-server version 3.6+ indexerar _id automatiskt fältet och shardnyckeln (endast i fragmenterade samlingar). API:et framtvingar automatiskt det unika _id fältet per shardnyckel.

API:et för MongoDB fungerar annorlunda än Azure Cosmos DB för NoSQL, som indexerar alla fält som standard.

Redigera indexeringsprincip

Vi rekommenderar att du redigerar din indexeringsprincip i Datautforskaren i Azure-portalen. Du kan lägga till index med enkla fält och jokertecken från indexeringsprincipredigeraren i Datautforskaren:

Indexing policy editor

Kommentar

Du kan inte skapa sammansatta index med hjälp av indexeringsprincipredigeraren i Datautforskaren.

Indextyper

Enskilt fält

Du kan skapa index på ett enda fält. Sorteringsordningen för det enskilda fältindexet spelar ingen roll. Följande kommando skapar ett index i fältet name:

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

Du kan skapa samma index för ett enda fält i name Azure-portalen:

Add name index in indexing policy editor

En fråga använder flera index med ett enda fält där det är tillgängligt. Du kan skapa upp till 500 enskilda fältindex per samling.

Sammansatta index (MongoDB-serverversion 3.6+)

I API:et för MongoDB krävs sammansatta index om frågan behöver kunna sorteras på flera fält samtidigt. För frågor med flera filter som inte behöver sorteras skapar du flera index med ett enda fält i stället för ett sammansatt index för att spara på indexeringskostnader.

Ett sammansatt index eller ett enda fältindex för varje fält i det sammansatta indexet resulterar i samma prestanda för filtrering i frågor.

Sammansatta index i kapslade fält stöds inte som standard på grund av begränsningar med matriser. Om det kapslade fältet inte innehåller en matris fungerar indexet som avsett. Om det kapslade fältet innehåller en matris (var som helst på sökvägen) ignoreras det värdet i indexet.

Ett sammansatt index som innehåller people.dylan.age fungerar till exempel i det här fallet eftersom det inte finns någon matris på sökvägen:

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

Samma sammansatta index fungerar inte i det här fallet eftersom det finns en matris i sökvägen:

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

Den här funktionen kan aktiveras för ditt databaskonto genom att aktivera funktionen "EnableUniqueCompoundNestedDocs".

Kommentar

Du kan inte skapa sammansatta index på matriser.

Följande kommando skapar ett sammansatt index för fälten name och age:

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

Du kan använda sammansatta index för att sortera effektivt på flera fält samtidigt, enligt följande exempel:

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

Du kan också använda föregående sammansatta index för att effektivt sortera på en fråga med motsatt sorteringsordning på alla fält. Här är ett exempel:

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

Sekvensen för sökvägarna i det sammansatta indexet måste dock exakt matcha frågan. Här är ett exempel på en fråga som skulle kräva ytterligare ett sammansatt index:

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

Multikey-index

Azure Cosmos DB skapar multikey-index för indexering av innehåll som lagras i matriser. Om du indexerar ett fält med ett matrisvärde indexerar Azure Cosmos DB automatiskt varje element i matrisen.

Geospatiala index

Många geospatiala operatorer kommer att dra nytta av geospatiala index. För närvarande stöder 2dsphere Azure Cosmos DB for MongoDB index. API:et har ännu inte stöd för 2d index.

Här är ett exempel på hur du skapar ett geospatialt index i location fältet:

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

Textindex

Azure Cosmos DB for MongoDB stöder för närvarande inte textindex. För textsökningsfrågor i strängar bör du använda Azure AI Search-integrering med Azure Cosmos DB.

Jokerteckenindex

Du kan använda jokerteckenindex för att stödja frågor mot okända fält. Anta att du har en samling som innehåller data om familjer.

Här är en del av ett exempeldokument i samlingen:

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

Här är ett annat exempel, den här gången med en något annorlunda uppsättning egenskaper i children:

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

I den här samlingen kan dokument ha många olika möjliga egenskaper. Om du vill indexering av alla data i matrisen children har du två alternativ: skapa separata index för varje enskild egenskap eller skapa ett jokerteckenindex för hela children matrisen.

Skapa ett jokerteckenindex

Följande kommando skapar ett jokerteckenindex för alla egenskaper i children:

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

Till skillnad från i MongoDB kan jokerteckenindex stödja flera fält i frågepredikat. Det blir ingen skillnad i frågeprestanda om du använder ett enda jokerteckenindex i stället för att skapa ett separat index för varje egenskap.

Du kan skapa följande indextyper med jokerteckensyntax:

  • Enskilt fält
  • Geospatial

Indexera alla egenskaper

Så här kan du skapa ett jokerteckenindex för alla fält:

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

Du kan också skapa jokerteckenindex med hjälp av Datautforskaren i Azure-portalen:

Add wildcard index in indexing policy editor

Kommentar

Om du precis har börjat utveckla rekommenderar vi starkt att du börjar med ett jokerteckenindex för alla fält. Detta kan förenkla utvecklingen och göra det enklare att optimera frågor.

Dokument med många fält kan ha en hög ru-avgift (Request Unit) för skrivningar och uppdateringar. Om du har en skrivintensiv arbetsbelastning bör du därför välja att individuellt indexsökvägar i stället för att använda jokerteckenindex.

Kommentar

Stöd för unikt index för befintliga samlingar med data finns i förhandsversionen. Den här funktionen kan aktiveras för ditt databaskonto genom att aktivera funktionen "EnableUniqueIndexReIndex".

Begränsningar

Jokerteckenindex stöder inte någon av följande indextyper eller egenskaper:

  • Sammansättning
  • TTL
  • Unik

Till skillnad från i MongoDB kan du i Azure Cosmos DB for MongoDB inte använda jokerteckenindex för:

  • Skapa ett jokerteckenindex som inkluderar flera specifika fält

    db.coll.createIndex(
        { "$**" : 1 },
        { "wildcardProjection " :
            {
               "children.givenName" : 1,
               "children.grade" : 1
            }
        }
    )
    
  • Skapa ett jokerteckenindex som exkluderar flera specifika fält

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

Alternativt kan du skapa flera jokerteckenindex.

Indexegenskaper

Följande åtgärder är vanliga för konton som hanterar wire protocol version 4.0 och konton som betjänar tidigare versioner. Du kan lära dig mer om index som stöds och indexerade egenskaper.

Unika index

Unika index är användbara för att framtvinga att två eller flera dokument inte innehåller samma värde för indexerade fält.

Följande kommando skapar ett unikt index i fältet student_id:

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

För fragmenterade samlingar måste du ange shardnyckeln (partition) för att skapa ett unikt index. Med andra ord är alla unika index i en fragmenterad samling sammansatta index där ett av fälten är shardnyckeln. Det första fältet i ordningen ska vara shardnyckeln.

Följande kommandon skapar en fragmenterad samling coll (shardnyckeln är university) med ett unikt index för fälten student_id och 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
}

Om du utelämnar "university":1 satsen i föregående exempel returneras ett fel med följande meddelande:

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

Begränsningar

Unika index måste skapas medan samlingen är tom.

Unika index för kapslade fält stöds inte som standard på grund av begränsningar med matriser. Om det kapslade fältet inte innehåller en matris fungerar indexet som avsett. Om det kapslade fältet innehåller en matris (var som helst på sökvägen) ignoreras det värdet i det unika indexet och unikheten bevaras inte för det värdet.

Ett unikt index på people.tom.age fungerar till exempel i det här fallet eftersom det inte finns någon matris på sökvägen:

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

men fungerar inte i det här fallet eftersom det finns en matris i sökvägen:

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

Den här funktionen kan aktiveras för ditt databaskonto genom att aktivera funktionen "EnableUniqueCompoundNestedDocs".

TTL-index

Om du vill aktivera förfallodatum för dokument i en viss samling måste du skapa ett TTL-index (time to live). Ett TTL-index är ett index i fältet _ts med ett expireAfterSeconds värde.

Exempel:

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

Föregående kommando tar bort alla dokument i db.coll samlingen som inte har ändrats under de senaste 10 sekunderna.

Kommentar

Fältet _ts är specifikt för Azure Cosmos DB och är inte tillgängligt från MongoDB-klienter. Det är en reserverad egenskap (system) som innehåller tidsstämpeln för dokumentets senaste ändring.

Spåra indexstatus

Version 3.6+ av Azure Cosmos DB for MongoDB stöder currentOp() kommandot för att spåra indexförloppet på en databasinstans. Det här kommandot returnerar ett dokument som innehåller information om pågående åtgärder på en databasinstans. Du använder currentOp kommandot för att spåra alla pågående åtgärder i den interna MongoDB. I Azure Cosmos DB for MongoDB stöder det här kommandot endast spårning av indexåtgärden.

Här följer några exempel som visar hur du använder currentOp kommandot för att spåra indexets förlopp:

  • Hämta index förloppet för en samling:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Hämta index förloppet för alla samlingar i en databas:

    db.currentOp({"command.$db": <databaseName>})
    
  • Hämta indexstatusen för alla databaser och samlingar i ett Azure Cosmos DB-konto:

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

Exempel på index förloppsutdata

Förloppsinformationen för indexet visar procentandelen för förloppet för den aktuella indexåtgärden. Här är ett exempel som visar utdatadokumentformatet för olika steg i indexets förlopp:

  • En indexåtgärd i en "foo"-samling och en "bar"-databas som är 60 procent färdig kommer att ha följande utdatadokument. Fältet Inprog[0].progress.total visar 100 som målslutprocent.

    {
          "inprog" : [
          {
                  ………………...
                  "command" : {
                          "createIndexes" : foo
                          "indexes" :[ ],
                          "$db" : bar
                  },
                  "msg" : "Index Build (background) Index Build (background): 60 %",
                  "progress" : {
                          "done" : 60,
                          "total" : 100
                  },
                  …………..…..
          }
          ],
          "ok" : 1
    }
    
  • Om en indexåtgärd precis har startats i en "foo"-samling och en "bar"-databas kan utdatadokumentet visa 0 procents förlopp tills den når en mätbar nivå.

    {
          "inprog" : [
          {
                  ………………...
                  "command" : {
                          "createIndexes" : foo
                          "indexes" :[ ],
                          "$db" : bar
                  },
                  "msg" : "Index Build (background) Index Build (background): 0 %",
                  "progress" : {
                          "done" : 0,
                          "total" : 100
                  },
                  …………..…..
          }
          ],
         "ok" : 1
    }
    
  • När den pågående indexåtgärden är klar visar utdatadokumentet tomma inprog åtgärder.

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

Uppdateringar av bakgrundsindex

Oavsett det värde som angetts för egenskapen Background Index görs indexuppdateringar alltid i bakgrunden. Eftersom indexuppdateringar använder enheter för programbegäran (RU: er) med lägre prioritet än andra databasåtgärder resulterar indexändringar inte i någon stilleståndstid för skrivningar, uppdateringar eller borttagningar.

Lästillgängligheten påverkas inte när du lägger till ett nytt index. Frågor använder bara nya index när indextransformeringen är klar. Under indextransformeringen fortsätter frågemotorn att använda befintliga index, så du ser liknande läsprestanda under indexeringstransformeringen som du hade observerat innan du initierade indexeringsändringen. När du lägger till nya index finns det heller ingen risk för ofullständiga eller inkonsekventa frågeresultat.

När du tar bort index och omedelbart kör frågor som har filter på de borttagna indexen kan resultaten vara inkonsekventa och ofullständiga tills indextransformeringen är klar. Om du tar bort index ger frågemotorn inte konsekventa eller fullständiga resultat när frågor filtrerar på dessa nyligen borttagna index. De flesta utvecklare släpper inte index och försöker sedan omedelbart fråga dem, så i praktiken är den här situationen osannolik.

Kommentar

Du kan spåra index förloppet.

ReIndex-kommando

Kommandot reIndex återskapar alla index i en samling. I vissa sällsynta fall kan frågeprestanda eller andra indexproblem i samlingen lösas genom att köra reIndex kommandot . Om du har problem med indexering är det en rekommenderad metod att återskapa indexen reIndex med kommandot.

Du kan köra reIndex kommandot med hjälp av följande syntax:

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

Du kan använda syntaxen nedan för att kontrollera om reIndex kommandot skulle förbättra frågeprestandan i samlingen:

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

Exempel på utdata:

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

Om reIndex förbättrar frågeprestandan är requiresReIndex sant. Om reIndex inte förbättrar frågeprestandan utelämnas den här egenskapen.

Migrera samlingar med index

För närvarande kan du bara skapa unika index när samlingen inte innehåller några dokument. Populära MongoDB-migreringsverktyg försöker skapa de unika indexen när data har importerats. Om du vill kringgå det här problemet kan du manuellt skapa motsvarande samlingar och unika index i stället för att låta migreringsverktyget prova. (Du kan uppnå det här beteendet med mongorestore hjälp --noIndexRestore av flaggan på kommandoraden.)

Indexering för MongoDB version 3.2

Tillgängliga indexeringsfunktioner och standardvärden skiljer sig åt för Azure Cosmos DB-konton som är kompatibla med version 3.2 av MongoDB-trådprotokollet. Du kan kontrollera ditt kontos version och uppgradera till version 3.6.

Om du använder version 3.2 beskrivs viktiga skillnader i det här avsnittet med version 3.6+.

Ta bort standardindex (version 3.2)

Till skillnad från version 3.6+ av Azure Cosmos DB för MongoDB indexerar version 3.2 varje egenskap som standard. Du kan använda följande kommando för att släppa dessa standardindex för en samling (coll):

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

När du har släppt standardindexen kan du lägga till fler index som i version 3.6+.

Sammansatta index (version 3.2)

Sammansatta index innehåller referenser till flera fält i ett dokument. Om du vill skapa ett sammansatt index uppgraderar du till version 3.6 eller 4.0.

Jokerteckenindex (version 3.2)

Om du vill skapa ett jokerteckenindex uppgraderar du till version 4.0 eller 3.6.

Nästa steg