Indexelés kezelése a MongoDB-hez készült Azure Cosmos DB-ben

A KÖVETKEZŐKRE VONATKOZIK: MongoDB

A MongoDB-hez készült Azure Cosmos DB kihasználja az Azure Cosmos DB alapvető indexkezelési képességeit. Ez a cikk az indexek MongoDB-hez készült Azure Cosmos DB használatával történő hozzáadására összpontosít. Az indexek olyan speciális adatstruktúrák, amelyek nagyjából nagyságrendekkel gyorsabban kérdezik le az adatokat.

A MongoDB-kiszolgáló 3.6-os és újabb verziójának indexelése

Az Azure Cosmos DB for MongoDB server 3.6+ verziója automatikusan indexeli a _id mezőt és a szegmenskulcsot (csak szegmenses gyűjteményekben). Az API automatikusan kikényszeríti a _id mező egyediségét szegmenskulcsonként.

A MongoDB API másképp viselkedik, mint az Azure Cosmos DB for NoSQL, amely alapértelmezés szerint az összes mezőt indexeli.

Indexelési szabályzat szerkesztése

Javasoljuk, hogy szerkessze az indexelési szabályzatot az Adatkezelőben az Azure Portalon. Az Indexelési szabályzat szerkesztőjében hozzáadhat egyetlen mező- és helyettesítő indexet az Adatkezelőben:

Indexing policy editor

Megjegyzés:

Összetett indexek nem hozhatók létre az Adatkezelő indexelési szabályzatszerkesztőjével.

Indextípusok

Egyetlen mező

Indexeket bármely mezőn létrehozhat. Az egymezős index rendezési sorrendje nem számít. A következő parancs létrehoz egy indexet a mezőben name:

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

Ugyanezt az egymezős indexet az Azure Portalon name is létrehozhatja:

Add name index in indexing policy editor

Egy lekérdezés több egymezős indexet használ, ahol elérhető. Gyűjteményenként legfeljebb 500 egymezős indexet hozhat létre.

Összetett indexek (MongoDB-kiszolgáló 3.6-os vagy újabb verziója)

A MongoDB API-ban összetett indexekre van szükség , ha a lekérdezésnek egyszerre több mezőre kell rendeznie. Több szűrővel rendelkező lekérdezések esetén, amelyeknek nincs szükség rendezésre, hozzon létre több egymezős indexet összetett index helyett az indexelési költségek megtakarításához.

Az összetett indexek vagy egymezős indexek az összetett index minden mezőjéhez ugyanazt a teljesítményt eredményezik a lekérdezések szűréséhez.

A beágyazott mezők összetett indexei alapértelmezés szerint nem támogatottak a tömbök korlátozásai miatt. Ha a beágyazott mező nem tartalmaz tömböt, az index a kívánt módon működik. Ha a beágyazott mező tartalmaz egy tömböt (bárhol az elérési úton), akkor a rendszer figyelmen kívül hagyja az értéket az indexben.

Ebben az esetben például egy összetett index people.dylan.age működik, mivel az elérési úton nincs tömb:

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

Ez az összetett index ebben az esetben nem működik, mivel egy tömb van az elérési úton:

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

Ez a funkció az "EnableUniqueCompoundNestedDocs" funkció engedélyezésével engedélyezhető az adatbázisfiók számára.

Megjegyzés:

Tömbökben nem hozhat létre összetett indexeket.

A következő parancs létrehoz egy összetett indexet a mezőkön name , és age:

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

Összetett indexek használatával egyszerre több mezőre is hatékonyan rendezhet, ahogy az alábbi példában is látható:

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

Az előző összetett index használatával is hatékonyan rendezhet egy olyan lekérdezést, amelynek minden mezőn ellentétes rendezési sorrendje van. Példa:

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

Az összetett indexben lévő elérési utak sorrendjének azonban pontosan meg kell egyeznie a lekérdezésével. Íme egy példa egy olyan lekérdezésre, amely további összetett indexet igényelne:

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

Többkulcsos indexek

Az Azure Cosmos DB többkulcsos indexeket hoz létre a tömbökben tárolt tartalmak indexeléséhez. Ha egy tömbértékkel rendelkező mezőt indexel, az Azure Cosmos DB automatikusan indexeli a tömb minden elemét.

Térinformatikai indexek

Számos térinformatikai operátor számára előnyös lesz a térinformatikai indexek használata. Az Azure Cosmos DB for MongoDB jelenleg támogatja 2dsphere az indexeket. Az API még nem támogatja 2d az indexeket.

Íme egy példa a mező térinformatikai indexének location létrehozására:

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

Szövegindexek

A MongoDB-hez készült Azure Cosmos DB jelenleg nem támogatja a szöveges indexeket. Sztringekre vonatkozó szöveges keresési lekérdezésekhez az Azure AI Search és az Azure Cosmos DB integrációját kell használnia.

Helyettesítő karakterek indexei

Helyettesítő indexekkel támogathatja az ismeretlen mezőkkel kapcsolatos lekérdezéseket. Tegyük fel, hogy rendelkezik egy olyan gyűjteménysel, amely a családokkal kapcsolatos adatokat tartalmazza.

Íme egy példadokumentum a gyűjteményben:

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

Íme egy másik példa, ezúttal egy kissé eltérő tulajdonságkészlettel a következőben children:

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

Ebben a gyűjteményben a dokumentumok számos különböző tulajdonságokkal rendelkezhetnek. Ha a children tömb összes adatát indexelni szeretné, két lehetőség közül választhat: külön indexeket hozhat létre minden egyes tulajdonsághoz, vagy létrehozhat egy helyettesítő indexet a teljes children tömbhöz.

Helyettesítő karakterek indexének létrehozása

Az alábbi parancs helyettesítő indexet hoz létre a következő tulajdonságokon belül children:

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

A MongoDB-vel ellentétben a helyettesítő karakterek indexei több mezőt is támogatnak a lekérdezési predikátumokban. Nem lesz különbség a lekérdezési teljesítményben, ha egyetlen helyettesítő indexet használ ahelyett, hogy minden tulajdonsághoz külön indexet hoz létre.

A következő indextípusokat helyettesítő karakterek szintaxisával hozhatja létre:

  • Egyetlen mező
  • Térinformatikai

Az összes tulajdonság indexelése

Az alábbiak szerint hozhat létre helyettesítő indexet az összes mezőn:

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

Helyettesítő indexeket az Adatkezelővel is létrehozhat az Azure Portalon:

Add wildcard index in indexing policy editor

Megjegyzés:

Ha csak most kezdi el a fejlesztést, javasoljuk, hogy kezdjen el helyettesítő indexet használni az összes mezőn. Ez leegyszerűsítheti a fejlesztést, és egyszerűbbé teheti a lekérdezések optimalizálását.

A sok mezőt tartalmazó dokumentumok írási és frissítési költsége magas lehet. Ezért ha írási terhelést igénylő számítási feladattal rendelkezik, érdemes egyéni indexelési útvonalakat választania a helyettesítő indexek használata helyett.

Megjegyzés:

Az adatokkal rendelkező meglévő gyűjtemények egyedi indexeinek támogatása előzetes verzióban érhető el. Ez a funkció az "EnableUniqueIndexReIndex" funkció engedélyezésével engedélyezhető az adatbázisfiók számára.

Limitations

A helyettesítő karakterek indexei nem támogatják az alábbi indextípusokat vagy tulajdonságokat:

  • Összetett
  • TTL
  • Egyedi

A MongoDB-vel ellentétben a MongoDB-hez készült Azure Cosmos DB-ben nem használhat helyettesítő indexeket a következőhöz:

  • Több megadott mezőt tartalmazó helyettesítő index létrehozása

    db.coll.createIndex(
        { "$**" : 1 },
        { "wildcardProjection " :
            {
               "children.givenName" : 1,
               "children.grade" : 1
            }
        }
    )
    
  • Több megadott mezőt nem tartalmazó helyettesítő index létrehozása

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

Másik lehetőségként létrehozhat több helyettesítő indexet.

Indextulajdonságok

A következő műveletek gyakoriak a Wire Protocol 4.0-s verzióját kiszolgáló fiókok és a korábbi verziókat kiszolgáló fiókok esetében. További információ a támogatott indexekről és az indexelt tulajdonságokról.

Egyedi indexek

Az egyedi indexek akkor hasznosak, ha kényszerítik, hogy két vagy több dokumentum ne tartalmazza ugyanazt az értéket az indexelt mezők esetében.

A következő parancs létrehoz egy egyedi indexet a mezőben student_id:

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

Szegmenses gyűjtemények esetén meg kell adnia a szegmens (partíció) kulcsot egy egyedi index létrehozásához. Más szóval a szegmenses gyűjtemények összes egyedi indexe összetett index, ahol az egyik mező a szegmenskulcs. A sorrend első mezőjének a szegmenskulcsnak kell lennie.

Az alábbi parancsok egy szegmenses gyűjteményt coll hoznak létre (a szegmenskulcs university) a mezők student_id egyedi indexével, és 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
}

Az előző példában a záradék kihagyása "university":1 hibát ad vissza a következő üzenettel:

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

Limitations

Egyedi indexeket kell létrehozni, amíg a gyűjtemény üres.

A beágyazott mezők egyedi indexei alapértelmezés szerint nem támogatottak a tömbök korlátozásai miatt. Ha a beágyazott mező nem tartalmaz tömböt, az index a kívánt módon fog működni. Ha a beágyazott mező tartalmaz egy tömböt (az elérési út bármely pontján), a rendszer figyelmen kívül hagyja az egyedi indexben ezt az értéket, és az egyediség nem marad meg az adott értéknél.

Ebben az esetben például a people.tom.age egyedi indexe működik, mivel az elérési úton nincs tömb:

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

de ebben az esetben nem fog működni, mivel egy tömb van az elérési úton:

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

Ez a funkció az "EnableUniqueCompoundNestedDocs" funkció engedélyezésével engedélyezhető az adatbázisfiók számára.

TTL-indexek

Ha engedélyezni szeretné a dokumentum lejáratát egy adott gyűjteményben, létre kell hoznia egy élettartam-indexet (TTL). A TTL-index egy értékekkel rendelkező expireAfterSeconds index a _ts mezőben.

Példa:

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

Az előző parancs törli a db.coll gyűjtemény azon dokumentumait, amelyeket az elmúlt 10 másodpercben nem módosítottak.

Megjegyzés:

A _ts mező az Azure Cosmos DB-hez tartozik, és nem érhető el a MongoDB-ügyfelekről. Ez egy fenntartott (rendszer)tulajdonság, amely a dokumentum utolsó módosításának időbélyegét tartalmazza.

Index állapotának nyomon követése

A MongoDB-hez készült Azure Cosmos DB 3.6+-os verziója támogatja a parancsot az currentOp() index előrehaladásának nyomon követéséhez egy adatbázispéldányon. Ez a parancs egy olyan dokumentumot ad vissza, amely információkat tartalmaz az adatbázispéldány folyamatban lévő műveleteiről. A parancs segítségével nyomon követheti az currentOp összes folyamatban lévő műveletet a natív MongoDB-ben. A MongoDB-hez készült Azure Cosmos DB-ben ez a parancs csak az indexművelet nyomon követését támogatja.

Íme néhány példa, amelyek bemutatják, hogyan használható a parancs az currentOp index előrehaladásának nyomon követésére:

  • Egy gyűjtemény indexállapotának lekérése:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Az adatbázis összes gyűjteményének indexállapotának lekérése:

    db.currentOp({"command.$db": <databaseName>})
    
  • Egy Azure Cosmos DB-fiók összes adatbázisának és gyűjteményének indexállapotának lekérése:

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

Példák az indexállapot kimenetére

Az index előrehaladási adatai az aktuális indexművelet előrehaladásának százalékos arányát mutatják. Íme egy példa, amely az index előrehaladásának különböző szakaszaihoz tartozó kimeneti dokumentum formátumát mutatja be:

  • A "foo" gyűjtemény és a "sáv" adatbázis 60%-os befejezett indexművelete a következő kimeneti dokumentumot fogja tartalmazni. A Inprog[0].progress.total mező a 100-as értéket jeleníti meg a cél befejezési százalékában.

    {
          "inprog" : [
          {
                  ………………...
                  "command" : {
                          "createIndexes" : foo
                          "indexes" :[ ],
                          "$db" : bar
                  },
                  "msg" : "Index Build (background) Index Build (background): 60 %",
                  "progress" : {
                          "done" : 60,
                          "total" : 100
                  },
                  …………..…..
          }
          ],
          "ok" : 1
    }
    
  • Ha egy indexművelet éppen most kezdődött egy "foo" gyűjteményen és "sáv" adatbázison, a kimeneti dokumentum 0 százalékos előrehaladást mutathat, amíg el nem éri a mérhető szintet.

    {
          "inprog" : [
          {
                  ………………...
                  "command" : {
                          "createIndexes" : foo
                          "indexes" :[ ],
                          "$db" : bar
                  },
                  "msg" : "Index Build (background) Index Build (background): 0 %",
                  "progress" : {
                          "done" : 0,
                          "total" : 100
                  },
                  …………..…..
          }
          ],
         "ok" : 1
    }
    
  • Amikor a folyamatban lévő indexművelet befejeződik, a kimeneti dokumentum üres inprog műveleteket jelenít meg.

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

Háttérindex frissítései

A Háttérindex tulajdonsághoz megadott értéktől függetlenül az indexfrissítések mindig a háttérben lesznek végrehajtva. Mivel az indexfrissítések a kérelemegységeket (kérelemegységeket) a többi adatbázisműveletnél alacsonyabb prioritással használják, az indexváltozások nem eredményeznek állásidőt az írásokhoz, frissítésekhez és törlésekhez.

Új index hozzáadásakor nincs hatással az olvasási rendelkezésre állásra. A lekérdezések csak akkor használják az új indexeket, ha az indexátalakítás befejeződött. Az indexátalakítás során a lekérdezési motor továbbra is meglévő indexeket fog használni, így az indexelési átalakítás során hasonló olvasási teljesítményt fog megfigyelni, mint amit az indexelés módosítása előtt megfigyelt. Új indexek hozzáadásakor nem áll fenn a hiányos vagy inkonzisztens lekérdezési eredmények kockázata.

Az indexek eltávolításakor és az elvetett indexeken szűrőket tartalmazó lekérdezések azonnali futtatásakor az eredmények inkonzisztensek és hiányosak lehetnek, amíg az indexátalakítás befejeződik. Ha eltávolítja az indexeket, a lekérdezési motor nem biztosít konzisztens vagy teljes eredményt, ha a lekérdezések az újonnan eltávolított indexekre szűrnek. A legtöbb fejlesztő nem dobja el az indexeket, majd azonnal megpróbálja lekérdezni őket, így a gyakorlatban ez a helyzet nem valószínű.

Megjegyzés:

Nyomon követheti az index előrehaladását.

ReIndex parancs

A reIndex parancs újra létrehozza a gyűjtemény összes indexét. Bizonyos ritka esetekben a lekérdezési teljesítmény vagy a gyűjtemény egyéb indexproblémái megoldhatók a reIndex parancs futtatásával. Ha problémákat tapasztal az indexelés során, ajánlott újra létrehozni az indexeket a reIndex paranccsal.

A parancsot a reIndex következő szintaxissal futtathatja:

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

Az alábbi szintaxis segítségével ellenőrizheti, hogy a parancs futtatása javítaná-e a reIndex lekérdezési teljesítményt a gyűjteményben:

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

Sample output:

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

Ha reIndex javítja a lekérdezési teljesítményt, a szükségesReIndex értéke igaz lesz. Ha reIndex nem javít a lekérdezési teljesítményen, a tulajdonság nem lesz elhagyva.

Gyűjtemények migrálása indexekkel

Jelenleg csak akkor hozhat létre egyedi indexeket, ha a gyűjtemény nem tartalmaz dokumentumokat. A népszerű MongoDB migrálási eszközök az adatok importálása után megpróbálják létrehozni az egyedi indexeket. A probléma megkerüléséhez manuálisan hozhatja létre a megfelelő gyűjteményeket és egyedi indexeket ahelyett, hogy lehetővé tenné az áttelepítési eszköz kipróbálását. (Ezt a viselkedést mongorestore a parancssorban található jelölő használatával --noIndexRestore érheti el.)

Indexelés a MongoDB 3.2-es verziójához

Az elérhető indexelési funkciók és alapértelmezett értékek eltérőek a MongoDB-protokoll 3.2-es verziójával kompatibilis Azure Cosmos DB-fiókok esetében. Ellenőrizheti a fiók verzióját, és frissíthet a 3.6-os verzióra.

Ha a 3.2-es verziót használja, ez a szakasz a 3.6-os verzióval kapcsolatos főbb különbségeket ismerteti.

Alapértelmezett indexek elvetése (3.2-es verzió)

A MongoDB-hez készült Azure Cosmos DB 3.6+-os verzióitól eltérően a 3.2-es verzió alapértelmezés szerint indexel minden tulajdonságot. A következő paranccsal elvetheti ezeket az alapértelmezett indexeket egy gyűjteményhez (coll):

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

Az alapértelmezett indexek elvetése után a 3.6-os verzióhoz hasonlóan további indexeket is hozzáadhat.

Összetett indexek (3.2-es verzió)

Az összetett indexek egy dokumentum több mezőjére vonatkozó hivatkozásokat tartalmaznak. Ha összetett indexet szeretne létrehozni, frissítsen a 3.6-os vagy a 4.0-s verzióra.

Helyettesítő karakterek indexei (3.2-es verzió)

Ha helyettesítő indexet szeretne létrehozni, frissítsen a 4.0-s vagy a 3.6-os verzióra.

További lépések