Condividi tramite


Gestire l'indicizzazione in Azure Cosmos DB for MongoDB

Azure Cosmos DB for MongoDB consente di usare l'indicizzazione per velocizzare le prestazioni delle query. Questo articolo illustra come gestire e ottimizzare gli indici per un recupero dei dati più rapido e una migliore efficienza.

Indicizzazione per il server MongoDB versione 3.6 e successive

Azure Cosmos DB per il server MongoDB versione 3.6+ indicizza automaticamente il _id campo e la chiave di partizione (solo nelle raccolte partizionate). L'API applica l'univocità del campo _id per ogni chiave di partizione.

L'API per MongoDB si comporta in modo diverso rispetto a Azure Cosmos DB for NoSQL, che indicizza tutti i campi per impostazione predefinita.

Modifica dei criteri di indicizzazione

Modificare i criteri di indicizzazione in Esplora dati nel portale di Azure. Aggiungere singoli campi e indici con caratteri jolly dall'editor dei criteri di indicizzazione in Esplora dati:

Screenshot dell'editor dei criteri di indicizzazione in Azure Cosmos DB for MongoDB.

Nota

Non è possibile creare indici composti usando l'editor dei criteri di indicizzazione in Esplora Dati.

Tipi di indice

Campo singolo

Creare un indice in un singolo campo. L'ordine dell'indice di campo singolo non è rilevante. Usare il comando seguente per creare un indice nel campo name:

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

Creare lo stesso indice di campo singolo in name nel portale di Azure:

Screenshot dell'aggiunta di un indice dei nomi nell'editor dei criteri di indicizzazione.

Una query usa più indici di campo singolo, se disponibili. Creare fino a 500 indici di campo singolo per raccolta.

Indici composti (server MongoDB versione 3.6+)

Nell'API per MongoDB usare indici composti con query che ordinano più campi contemporaneamente. Per le query con più filtri che non devono essere ordinati, creare più indici di campo singolo anziché un indice composto per risparmiare sui costi di indicizzazione.

Un indice composto o un indice di campo singolo per ogni campo nell'indice composto fornisce le stesse prestazioni di filtro nelle query.

Gli indici composti nei campi annidati non sono supportati per impostazione predefinita a causa delle limitazioni con le matrici. Se un campo annidato non contiene una matrice, l'indice funziona come previsto. Se un campo annidato contiene una matrice (in qualsiasi punto del percorso), quel valore viene ignorato nell'indice.

Ad esempio, un indice composto contenente people.dylan.age, funziona in questo caso perché non c'è nessuna matrice nel percorso:

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

Lo stesso indice composto non funziona in questo caso perché c'è una matrice nel percorso:

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

Abilitare questa funzionalità per l'account del database abilitando la funzionalità 'EnableUniqueCompoundNestedDocs'.

Nota

Non è possibile creare indici composti su matrici.

Il comando seguente crea un indice composto nei campi name e age:

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

È possibile usare indici composti per ordinare in modo efficiente più campi contemporaneamente, come mostrato nell'esempio seguente:

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

È anche possibile usare l'indice composto precedente per ordinare in modo efficiente una query con l'ordine di ordinamento opposto su tutti i campi. Ecco un esempio:

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

Tuttavia, la sequenza dei percorsi nell'indice composto deve corrispondere esattamente alla query. Di seguito è riportato un esempio di query che richiede un indice composto aggiuntivo:

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

Indici multichiave

Azure Cosmos DB crea indici multichiave per indicizzare il contenuto in matrici. Se si indicizza un campo con un valore di matrice, Azure Cosmos DB indicizza automaticamente ogni elemento nella matrice.

Indici geospaziali

Molti operatori geospaziali traggono vantaggio dagli indici geospaziali. Azure Cosmos DB for MongoDB supporta gli indici 2dsphere. L'API non supporta ancora gli indici 2d.

Di seguito è riportato un esempio di creazione di un indice geospaziale nel campo location:

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

Indici di testo

Azure Cosmos DB for MongoDB non supporta gli indici di testo. Per le query di ricerca di testo sulle stringhe, usare l'integrazione di Azure AI Search con Azure Cosmos DB.

Indici con caratteri jolly

Usare gli indici con caratteri jolly per supportare query su campi sconosciuti. Si supponga di creare una raccolta con dati relativi alle famiglie.

Di seguito è riportato parte di un documento di esempio in quella raccolta:

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

Ecco un altro esempio con un set diverso di proprietà in children:

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

I documenti in questa raccolta possono avere molte proprietà diverse. Per indicizzare tutti i dati nella matrice children, creare indici separati per ogni proprietà o creare un indice con caratteri jolly per l'intera matrice children.

Creare un indice jolly

Usare il comando seguente per creare un indice con caratteri jolly in qualsiasi proprietà all'interno di children:

db.coll.createIndex({"children.$**" : 1})
  • A differenza di MongoDB, gli indici jolly possono supportare più campi nei predicati di query. Non c'è alcuna differenza nelle prestazioni delle query se si usa un singolo indice con caratteri jolly anziché creare un indice separato per ogni proprietà.

Creare i tipi di indice seguenti usando la sintassi con caratteri jolly:

  • Campo singolo
  • GeoSpatial

Indicizzazione di tutte le proprietà

Creare un indice con caratteri jolly in tutti i campi con il comando seguente:

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

Creare indici con caratteri jolly usando Esplora dati nel portale di Azure:

Aggiungere un indice con caratteri jolly nell'editor dei criteri di indicizzazione

Nota

Se si sta iniziando lo sviluppo, iniziare con un indice con caratteri jolly in tutti i campi. Questo approccio semplifica lo sviluppo e semplifica l'ottimizzazione delle query.

I documenti con molti campi avranno un addebito elevato di unità richiesta (UR) per operazioni di scrittura e aggiornamenti. Se si dispone di un carico di lavoro con intensa attività di scrittura, usare percorsi indicizzati singolarmente anziché caratteri jolly.

Limiti

Gli indici con caratteri jolly non supportano i seguenti tipi o proprietà dell'indice:

  • Composto

  • TTL

  • Unico

  • A differenza di MongoDB, in Azure Cosmos DB for MongoDB non è possibile usare indici con caratteri jolly per:

  • Creare un indice wildcard che includa più campi

    db.coll.createIndex(
      { "$**" : 1 },
      { "wildcardProjection " :
        {
          "children.givenName" : 1,
          "children.grade" : 1
        }
      }
    )
    
  • Creare un indice con carattere jolly che esclude più campi specifici

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

In alternativa, creare più indici con caratteri jolly.

Proprietà degli indici

Le operazioni seguenti sono comuni per gli account che usano il protocollo wire versione 4.0 e le versioni precedenti. Altre informazioni sugli indici supportati e proprietà indicizzate.

Indici univoci

Gli indici univoci consentono di assicurarsi che due o più documenti non abbiano lo stesso valore per i campi indicizzati.

Eseguire il comando seguente per creare un indice univoco nel campo student_id:

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

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

Per le raccolte partizionate, specificare la chiave di partizione (partizione) per creare un indice univoco. Tutti gli indici univoci di una raccolta partizionata sono indici composti e uno dei campi è la chiave di partizione. La chiave di partizione deve essere il primo campo nella definizione dell'indice.

Eseguire i comandi seguenti per creare una raccolta partizionata denominata coll (con university come chiave di partizione) e un indice univoco nei campi student_id e 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
}

Se si omette la clausola "university":1 nell'esempio precedente, viene visualizzato il messaggio di errore seguente:

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

Limiti

Creare indici univoci mentre la raccolta è vuota.

Gli account Azure Cosmos DB per MongoDB con backup continuo non supportano la creazione di un indice univoco per una raccolta esistente. Per un account di questo tipo, è necessario creare indici univoci insieme alla creazione della raccolta, che deve e può essere eseguita solo usando i comandi di creazione dell'estensione della raccolta.

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

Gli indici univoci nei campi annidati non sono supportati per impostazione predefinita a causa delle limitazioni con le matrici. Se il campo annidato non contiene una matrice, l'indice funziona come previsto. Se il campo annidato contiene una matrice (in qualsiasi punto del percorso), quel valore è ignorato nell'indice univoco e l'univocità non è mantenuta per quel valore.

Ad esempio, un indice univoco su people.tom.age funziona in questo caso perché nel percorso non è presente alcuna matrice:

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

Ma in questo caso non funziona perché nel percorso è presente una matrice:

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

Questa funzionalità può essere abilitata per l'account del database abilitando la funzionalità 'EnableUniqueCompoundNestedDocs'.

Indici TTL

Per consentire la scadenza dei documenti in una raccolta, creare un indice TTL (Time-to-Live). Un indice TTL è un indice nel campo _ts con un valore expireAfterSeconds.

Esempio:

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

Il comando precedente elimina tutti i documenti della raccolta db.coll modificati più di 10 secondi fa.

Nota

Il campo _ts è specifico di Azure Cosmos DB e non è accessibile dai client MongoDB. Si tratta di una proprietà di sistema riservata che contiene il timestamp dell'ultima modifica del documento.

Monitorare lo stato dell'indice

La versione 3.6+ di Azure Cosmos DB for MongoDB supporta il comando currentOp() per monitorare lo stato di avanzamento dell'indice su un'istanza del database. Con questo comando si ottiene un documento contenente informazioni sulle operazioni in corso su un'istanza del database. Usare il comando currentOp per monitorare tutte le operazioni in corso in MongoDB nativo. In Azure Cosmos DB for MongoDB questo comando tiene solamente traccia dell'operazione sull'indice.

Ecco alcuni esempi di come usare il comando currentOp per monitorare l'avanzamento dell'indice:

  • Ottenere lo stato di avanzamento dell'indice per una raccolta:

    db.currentOp({"command.createIndexes": <collectionName>, "command.$db": <databaseName>})
    
  • Ottenere lo stato di avanzamento dell'indice per tutte le raccolte in un database:

    db.currentOp({"command.$db": <databaseName>})
    
  • Ottenere lo stato di avanzamento dell'indice per tutti i database e le raccolte in un account Azure Cosmos DB:

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

Esempi di output dello stato di avanzamento dell'indice

Le informazioni sullo stato di avanzamento dell'indice illustrano la percentuale di avanzamento dell'operazione sull'indice corrente. Di seguito sono riportati degli esempi che mostrano il formato del documento di output per diverse fasi dell'avanzamento dell'indice:

  • Un'operazione sull'indice su una raccolta "foo" e un database "bar" completo al 60% ha il documento di output seguente. Il campo Inprog[0].progress.total mostra 100 come percentuale di completamento finale.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 60 %",
          "progress": {
            "done": 60,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • Se un'operazione sull'indice è stata appena avviata in una raccolta "foo" e in un database "bar", il documento di output potrebbe illustrare lo stato di avanzamento dello 0% fino a quando non raggiunge un livello misurabile.

    {
      "inprog": [
        {
          ...
          "command": {
            "createIndexes": foo
            "indexes": [],
            "$db": bar
          },
          "msg": "Index Build (background) Index Build (background): 0 %",
          "progress": {
            "done": 0,
            "total": 100
          },
          ...
        }
      ],
      "ok": 1
    }
    
  • Al termine dell'operazione sull'indice, il documento di output illustra le operazioni inprog vuote.

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

Aggiornamenti degli indici in background

Gli aggiornamenti degli indici vengono sempre eseguiti in background, indipendentemente dal valore impostato per la proprietà Indice In background. Poiché gli aggiornamenti degli indici utilizzano unità richiesta (RU) con una priorità inferiore rispetto ad altre azioni di database, le modifiche all'indice non comportano tempi di inattività per scritture, aggiornamenti o eliminazioni.

L'aggiunta di un nuovo indice non influisce sulla disponibilità in lettura. Le query usano nuovi indici solo al termine della trasformazione dell'indice. Durante la trasformazione, il motore di query continua a usare gli indici esistenti, in modo da visualizzare prestazioni di lettura simili a prima di avviare la modifica dell'indicizzazione. L'aggiunta di nuovi indici non comporta il rischio di risultati di query incompleti o incoerenti.

Se si rimuovono gli indici e si eseguono immediatamente query con filtri sugli indici eliminati, i risultati potrebbero essere incoerenti e incompleti fino al termine della trasformazione dell'indice. Il motore di query non fornisce risultati coerenti o completi per le query che filtrano sugli indici appena rimossi. La maggior parte degli sviluppatori non elimina gli indici e quindi li esegue immediatamente una query, quindi questa situazione è improbabile.

Nota

È possibile monitorare lo stato dell'indice.

Comando reIndex

Il comando reIndex ricrea tutti gli indici di una raccolta. In rari casi, l'esecuzione del comando reIndex può risolvere i problemi di prestazioni delle query o altri problemi di indice nella raccolta. Se si verificano problemi di indicizzazione, provare a ricreare gli indici con il comando reIndex.

Eseguire il comando reIndex usando la sintassi seguente:

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

Usare la sintassi seguente per verificare se l'esecuzione del comando reIndex migliora le prestazioni delle query nella raccolta:

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

Output di esempio:

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

Se reIndex migliora le prestazioni delle query, requiresReIndex è true. Se reIndex non migliora le prestazioni delle query, questa proprietà viene omessa.

Eseguire la migrazione di raccolte con indici

È possibile creare indici univoci solo quando la raccolta non contiene documenti. Gli strumenti di migrazione di MongoDB più diffusi cercano di creare gli indici univoci dopo l'importazione dei dati. Per aggirare questo problema, creare manualmente le raccolte e gli indici univoci corrispondenti anziché usare lo strumento di migrazione. È possibile ottenere questo comportamento per mongorestore, usando il flag --noIndexRestore nella riga di comando.

Indicizzazione per MongoDB versione 3.2

Le funzionalità di indicizzazione e le impostazioni predefinite variano per gli account Azure Cosmos DB che usano la versione 3.2 del protocollo wire MongoDB. Controllare la versione dell'account in feature-support-36.md#protocol-support e eseguire l'aggiornamento alla versione 3.6 in upgrade-version.md.

Se si usa la versione 3.2, questa sezione evidenzia le differenze principali rispetto alle versioni 3.6 e successive.

Eliminazione degli indici predefiniti (versione 3.2)

A differenza delle versioni 3.6 e successive, la versione 3.2 di Azure Cosmos DB for MongoDB indicizza ogni proprietà per impostazione predefinita. Usare il comando seguente per eliminare questi indici predefiniti per una raccolta (coll):

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

Dopo l'eliminazione degli indici predefiniti, aggiungere altri indici come si fa nella versione 3.6 e successive.

Indici composti (versione 3.2)

Gli indici composti fanno riferimento a più campi in un documento. Per creare un indice composto, eseguire l'aggiornamento alla versione 3.6 o 4.0 in upgrade-version.md.

Indici jolly (versione 3.2)

Per creare un indice con caratteri jolly, eseguire l'aggiornamento alla versione 4.0 o 3.6 in upgrade-version.md.

Passaggi successivi