Udostępnij za pomocą


Zarządzanie indeksowaniem w usłudze Azure Cosmos DB dla bazy danych MongoDB

Usługa Azure Cosmos DB dla bazy danych MongoDB umożliwia korzystanie z indeksowania w celu przyspieszenia wydajności zapytań. W tym artykule pokazano, jak zarządzać indeksami i optymalizować je w celu szybszego pobierania danych i lepszej wydajności.

Indeksowanie dla serwera MongoDB w wersji 3.6 lub nowszej

Serwer usługi Azure Cosmos DB dla bazy danych MongoDB w wersji 3.6 lub nowszej automatycznie indeksuje _id pole i klucz fragmentu (tylko w kolekcjach podzielonych na fragmenty). Interfejs API wymusza unikatowość _id pola na klucz fragmentu.

Interfejs API dla bazy danych MongoDB działa inaczej niż usługa Azure Cosmos DB for NoSQL, która domyślnie indeksuje wszystkie pola.

Edytowanie zasad indeksowania

Edytuj zasady indeksowania w Eksploratorze danych w witrynie Azure Portal. Dodaj pojedyncze pole i indeksy wieloznaczne z edytora zasad indeksowania w Eksploratorze danych:

Zrzut ekranu przedstawiający edytor zasad indeksowania w usłudze Azure Cosmos DB dla bazy danych MongoDB.

Uwaga

Nie można tworzyć indeksów złożonych przy użyciu edytora zasad indeksowania w Eksploratorze danych.

Typy indeksów

Jedno pole

Utwórz indeks w dowolnym pojedynczym polu. Kolejność sortowania indeksu pojedynczego pola nie ma znaczenia. Użyj następującego polecenia, aby utworzyć indeks w polu name:

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

Utwórz ten sam indeks name pojedynczego pola w witrynie Azure Portal:

Zrzut ekranu przedstawiający dodawanie indeksu nazw w edytorze zasad indeksowania.

Zapytanie używa wielu pojedynczych indeksów pól, jeśli są dostępne. Utwórz maksymalnie 500 indeksów pojedynczych pól na kolekcję.

Indeksy złożone (serwer MongoDB w wersji 3.6 lub nowszej)

W interfejsie API dla bazy danych MongoDB użyj indeksów złożonych z zapytaniami, które sortuje wiele pól jednocześnie. W przypadku zapytań z wieloma filtrami, które nie muszą sortować, utwórz wiele indeksów z jednym polem zamiast indeksu złożonego, aby zaoszczędzić na kosztach indeksowania.

Indeks złożony lub indeksy pojedynczego pola dla każdego pola w indeksie złożonym powodują taką samą wydajność filtrowania w zapytaniach.

Indeksy złożone w zagnieżdżonych polach nie są domyślnie obsługiwane z powodu ograniczeń dotyczących tablic. Jeśli zagnieżdżone pole nie ma tablicy, indeks działa zgodnie z oczekiwaniami. Jeśli zagnieżdżone pole ma tablicę w dowolnym miejscu na ścieżce, ta wartość jest ignorowana w indeksie.

Na przykład indeks złożony zawierający people.dylan.age działa w tym przypadku, ponieważ w ścieżce nie ma tablicy:

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

Ten sam indeks złożony nie działa w tym przypadku, ponieważ w ścieżce znajduje się tablica:

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

Włącz tę funkcję dla konta bazy danych, włączając funkcję "EnableUniqueCompoundNestedDocs".

Uwaga

Nie można tworzyć indeksów złożonych w tablicach.

Następujące polecenie tworzy indeks złożony w polach name i age:

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

Indeksy złożone umożliwiają efektywne sortowanie wielu pól jednocześnie, jak pokazano w poniższym przykładzie:

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

Możesz również użyć powyższego indeksu złożonego, aby efektywnie sortować zapytanie z przeciwną kolejnością sortowania we wszystkich polach. Oto przykład:

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

Jednak sekwencja ścieżek w indeksie złożonym musi dokładnie odpowiadać zapytaniu. Oto przykład zapytania, które wymagałoby dodatkowego indeksu złożonego:

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

Indeksy wieloklucze

Usługa Azure Cosmos DB tworzy indeksy wieloklucze w celu indeksowania zawartości w tablicach. Jeśli indeksujesz pole z wartością tablicy, usługa Azure Cosmos DB automatycznie indeksuje każdy element w tablicy.

Indeksy geoprzestrzenne

Wiele operatorów geoprzestrzennych korzysta z indeksów geoprzestrzennych. Usługa Azure Cosmos DB dla bazy danych MongoDB obsługuje 2dsphere indeksy. Interfejs API nie obsługuje 2d jeszcze indeksów.

Oto przykład tworzenia indeksu geoprzestrzennego w location polu:

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

Indeksy tekstowe

Usługa Azure Cosmos DB dla bazy danych MongoDB nie obsługuje indeksów tekstowych. W przypadku zapytań wyszukiwania tekstu w ciągach użyj integracji usługi Azure AI Search z usługą Azure Cosmos DB.

Indeksy wieloznaczne

Użyj indeksów wieloznacznych, aby obsługiwać zapytania dotyczące nieznanych pól. Wyobraź sobie kolekcję zawierającą dane dotyczące rodzin.

Oto część przykładowego dokumentu w tej kolekcji:

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

Oto inny przykład z innym zestawem właściwości w pliku children:

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

Dokumenty w tej kolekcji mogą mieć wiele różnych właściwości. Aby zaindeksować wszystkie dane w children tablicy, utwórz oddzielne indeksy dla każdej właściwości lub utwórz jeden indeks wieloznaczny dla całej children tablicy.

Utwórz indeks zastępczy

Użyj następującego polecenia, aby utworzyć indeks wieloznaczny we wszystkich właściwościach w programie children:

db.coll.createIndex({"children.$**" : 1})
  • W przeciwieństwie do bazy danych MongoDB indeksy wieloznaczne mogą obsługiwać wiele pól w predykatach zapytań. Nie ma różnicy w wydajności zapytań, jeśli używasz pojedynczego indeksu wieloznacznych zamiast tworzenia oddzielnego indeksu dla każdej właściwości.

Utwórz następujące typy indeksów przy użyciu składni symboli wieloznacznych:

  • Jedno pole
  • Dane geoprzestrzenne

Indeksowanie wszystkich właściwości

Utwórz indeks wieloznaczny we wszystkich polach za pomocą następującego polecenia:

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

Tworzenie indeksów wieloznacznych przy użyciu Eksploratora danych w witrynie Azure Portal:

Dodawanie indeksu wieloznacznych w edytorze zasad indeksowania

Uwaga

Jeśli dopiero zaczynasz programowanie, zacznij od indeksu z symbolami wieloznacznymi we wszystkich polach. Takie podejście upraszcza programowanie i ułatwia optymalizowanie zapytań.

W przypadku zapisów i aktualizacji dokumenty z wieloma polami mogą być naliczane wysokie opłaty za jednostkę żądania (RU). Jeśli masz duże obciążenie zapisu, użyj indywidualnie indeksowanych ścieżek zamiast symboli wieloznacznych.

Ograniczenia

Indeksy wieloznaczne nie obsługują żadnego z następujących typów indeksów ani właściwości:

  • Złożony

  • Czas wygaśnięcia

  • Unikatowe

  • W przeciwieństwie do bazy danych MongoDB w usłudze Azure Cosmos DB dla bazy danych MongoDB nie można używać indeksów wieloznacznych dla:

  • Tworzenie indeksu wieloznacznego, który uwzględnia wiele konkretnych pól

    db.coll.createIndex(
      { "$**" : 1 },
      { "wildcardProjection " :
        {
          "children.givenName" : 1,
          "children.grade" : 1
        }
      }
    )
    
  • Tworzenie indeksu wieloznacznego, który wyklucza wiele konkretnych pól

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

Alternatywnie utwórz wiele indeksów wieloznacznych.

Właściwości indeksu

Następujące operacje są typowe dla kont korzystających z protokołu przewodowego w wersji 4.0 i starszych. Dowiedz się więcej o obsługiwanych indeksach i właściwościach indeksowanych.

Indeksy unikatowe

Indeksy unikatowe pomagają upewnić się, że co najmniej dwa dokumenty nie mają tej samej wartości dla indeksowanych pól.

Uruchom następujące polecenie, aby utworzyć unikatowy indeks w student_id polu:

db.coll.createIndex( { "student_id" : 1 }, {unique:true} )

{
  "_t" : "CreateIndexesResponse",
  "ok" : 1,
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 1,
  "numIndexesAfter" : 4
}

W przypadku kolekcji podzielonych na fragmenty podaj klucz fragmentu (partycji), aby utworzyć unikatowy indeks. Wszystkie indeksy unikatowe w kolekcji podzielonej na fragmenty są indeksami złożonymi, a jednym z pól jest klucz fragmentu. Klucz fragmentu powinien być pierwszym polem w definicji indeksu.

Uruchom następujące polecenia, aby utworzyć kolekcję z fragmentami o nazwie coll (z kluczem university fragmentu) i unikatowym indeksem w polach student_id i university :

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

Jeśli pominiesz klauzulę "university":1 w poprzednim przykładzie, zostanie wyświetlony następujący komunikat o błędzie:

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

Ograniczenia

Utwórz unikatowe indeksy, gdy kolekcja jest pusta.

Konta usługi Azure Cosmos DB dla bazy danych MongoDB z ciągłą kopią zapasową nie obsługują tworzenia unikatowego indeksu dla istniejącej kolekcji. W przypadku takiego konta unikatowe indeksy muszą być tworzone jednocześnie z tworzeniem kolekcji, co można i trzeba zrobić wyłącznie przy użyciu poleceń rozszerzenia tworzenia kolekcji.

db.runCommand({customAction:"CreateCollection", collection:"coll", shardKey:"student_id", indexes:[
{key: { "student_id" : 1}, name:"student_id_1", unique: true}
]});

Indeksy unikatowe w polach zagnieżdżonych nie są domyślnie obsługiwane z powodu ograniczeń dotyczących tablic. Jeśli zagnieżdżone pole nie ma tablicy, indeks działa zgodnie z oczekiwaniami. Jeśli zagnieżdżone pole ma tablicę w dowolnym miejscu na ścieżce, ta wartość jest ignorowana w indeksie unikatowym, a unikatowość nie jest zachowywana dla tej wartości.

Na przykład unikatowy indeks w people.tom.age tym przypadku działa, ponieważ w ścieżce nie ma tablicy:

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

Ale w tym przypadku nie działa, ponieważ w ścieżce znajduje się tablica:

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

Tę funkcję można włączyć dla konta bazy danych, włączając funkcję "EnableUniqueCompoundNestedDocs".

Indeksy czasu wygaśnięcia

Aby zezwolić na wygaśnięcie dokumentów w kolekcji, utwórz indeks czasu wygaśnięcia (TTL). Indeks czasu wygaśnięcia jest indeksem w _ts polu z wartością expireAfterSeconds .

Przykład:

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

Poprzednie polecenie usuwa wszystkie dokumenty w db.coll kolekcji, które zostały zmodyfikowane ponad 10 sekund temu.

Uwaga

Pole _ts jest specyficzne dla usługi Azure Cosmos DB i nie jest dostępne z klientów bazy danych MongoDB. Jest to właściwość zarezerwowana (systemowa), która zawiera sygnaturę czasową ostatniej modyfikacji dokumentu.

Śledzenie postępu indeksu

Wersja 3.6 lub nowsza usługi Azure Cosmos DB dla bazy danych MongoDB obsługuje currentOp() polecenie umożliwiające śledzenie postępu indeksowania w wystąpieniu bazy danych. To polecenie zwraca dokument z informacjami o operacjach w toku w wystąpieniu bazy danych. Użyj polecenia , currentOp aby śledzić wszystkie operacje w toku w natywnej bazie danych MongoDB. W usłudze Azure Cosmos DB dla bazy danych MongoDB to polecenie śledzi tylko operację indeksu.

Oto kilka przykładów użycia currentOp polecenia do śledzenia postępu indeksu:

  • Pobieranie postępu indeksu dla kolekcji:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Pobierz postęp indeksu dla wszystkich kolekcji w bazie danych:

    db.currentOp({"command.$db": <databaseName>})
    
  • Uzyskaj postęp indeksu dla wszystkich baz danych i kolekcji na koncie usługi Azure Cosmos DB:

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

Przykłady wyników postępu indeksu

Szczegóły postępu indeksu pokazują procent postępu bieżącej operacji indeksu. Oto przykłady formatu dokumentu wyjściowego dla różnych etapów postępu indeksu:

  • Operacja indeksu w kolekcji "foo" i bazie danych "bar", która jest ukończona w 60 procentach, ma następujący dokument wyjściowy. Pole Inprog[0].progress.total zawiera wartość 100 jako docelową wartość procentową ukończenia.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 60 %",
          "progress": {
            "done": 60,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • Jeśli operacja indeksu właśnie została uruchomiona w kolekcji "foo" i bazie danych "bar", dokument wyjściowy może pokazać postęp 0 procent, dopóki nie osiągnie mierzalnego poziomu.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 0 %",
          "progress": {
            "done": 0,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • Po zakończeniu operacji indeksowania dokument wyjściowy wyświetla puste inprog operacje.

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

Aktualizacje indeksu w tle

Aktualizacje indeksu są zawsze uruchamiane w tle, niezależnie od wartości ustawionej dla właściwości indeksu w tle . Ponieważ aktualizacje indeksu używają jednostek żądań (RU) o niższym priorytekcie niż inne akcje bazy danych, zmiany indeksu nie powodują przestoju operacji zapisu, aktualizacji ani usuwania.

Dodanie nowego indeksu nie wpływa na dostępność odczytu. Zapytania używają nowych indeksów dopiero po zakończeniu transformacji indeksu. Podczas transformacji aparat zapytań nadal korzysta z istniejących indeksów, więc zobaczysz podobną wydajność odczytu, jak przed rozpoczęciem zmiany indeksowania. Dodanie nowych indeksów nie powoduje ryzyka niekompletnych ani niespójnych wyników zapytania.

Jeśli usuniesz indeksy i natychmiast uruchomisz zapytania filtrujące te porzucone indeksy, wyniki mogą być niespójne i niekompletne do momentu zakończenia transformacji indeksu. Aparat zapytań nie udostępnia spójnych ani kompletnych wyników dla zapytań filtrujących nowo usunięte indeksy. Większość deweloperów nie usuwa indeksów, a następnie natychmiast wysyła do nich zapytania, więc sytuacja jest mało prawdopodobna.

reIndex polecenie

Polecenie reIndex ponownie utworzy wszystkie indeksy w kolekcji. W rzadkich przypadkach uruchomienie reIndex polecenia może rozwiązać problemy z wydajnością zapytań lub innymi indeksami w kolekcji. Jeśli występują problemy z indeksowaniem, spróbuj ponownie utworzyć indeksy za reIndex pomocą polecenia .

reIndex Uruchom polecenie przy użyciu następującej składni:

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

Użyj następującej składni, aby sprawdzić, czy uruchomienie reIndex polecenia poprawia wydajność zapytań w kolekcji:

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

Przykładowe dane wyjściowe:

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

Jeśli reIndex poprawia wydajność zapytań, właściwość requiresReIndex ma wartość true. Jeśli reIndex nie poprawi wydajności zapytań, ta właściwość zostanie pominięta.

Migrowanie kolekcji z indeksami

Indeksy unikatowe można tworzyć tylko wtedy, gdy kolekcja nie ma dokumentów. Popularne narzędzia migracji bazy danych MongoDB próbują utworzyć unikatowe indeksy po zaimportowaniu danych. Aby obejść ten problem, należy ręcznie utworzyć odpowiednie kolekcje i unikatowe indeksy zamiast pozwolić narzędziu do migracji. To zachowanie mongorestore można osiągnąć za pomocą flagi --noIndexRestore w wierszu polecenia.

Indeksowanie bazy danych MongoDB w wersji 3.2

Funkcje indeksowania i wartości domyślne różnią się w przypadku kont usługi Azure Cosmos DB, które używają wersji 3.2 protokołu przewodowego bazy danych MongoDB. Sprawdź wersję konta pod adresem feature-support-36.md#protocol-support i uaktualnij go do wersji 3.6 pod adresem upgrade-version.md.

Jeśli używasz wersji 3.2, w tej sekcji wyróżniono najważniejsze różnice między wersjami 3.6 i nowszymi.

Usuwanie indeksów domyślnych (wersja 3.2)

W przeciwieństwie do wersji 3.6 lub nowszej usługa Azure Cosmos DB dla bazy danych MongoDB domyślnie indeksuje każdą właściwość w wersji 3.2. Użyj następującego polecenia, aby usunąć te domyślne indeksy dla kolekcji (coll):

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

Po usunięciu indeksów domyślnych dodaj więcej indeksów w wersji 3.6 lub nowszej.

Indeksy złożone (wersja 3.2)

Indeksy złożone odwołują się do wielu pól w dokumencie. Aby utworzyć indeks złożony, przeprowadź uaktualnienie do wersji 3.6 lub 4.0 w upgrade-version.md.

Indeksy wieloznaczne (wersja 3.2)

Aby utworzyć indeks wieloznaczny, przeprowadź uaktualnienie do wersji 4.0 lub 3.6 w upgrade-version.md.

Następne kroki