Indexing policies in Azure Cosmos DB (Criteri di indicizzazione in Azure Cosmos DB)
SI APPLICA A: NoSQL
In Azure Cosmos DB, ogni contenitore dispone di un criterio di indicizzazione che determina come devono essere indicizzati gli elementi del contenitore. I criteri di indicizzazione predefiniti per i contenitori appena creati indicizzano ogni proprietà di ogni elemento e applicano indici di intervallo per qualsiasi stringa o numero. Ciò consente di ottenere prestazioni di query ottimali senza dover pensare all'indicizzazione e alla gestione degli indici in anticipo.
In alcune situazioni potrebbe essere necessario eseguire l'override di questo comportamento automatico per soddisfare al meglio le proprie esigenze. È possibile personalizzare i criteri di indicizzazione di un contenitore impostandone la modalità di indicizzazione e includendo o escludendo i percorsi delle proprietà.
Nota
Il metodo di aggiornamento dei criteri di indicizzazione descritto in questo articolo si applica solo all’API Azure Cosmos DB per NoSQL. Informazioni sull'indicizzazione nell'API di Azure Cosmos DB per MongoDB
Modalità di indicizzazione
Azure Cosmos DB supporta due modalità di indicizzazione:
- Coerente: l'indice viene aggiornato in modo sincrono durante la creazione, l'aggiornamento o l'eliminazione di elementi. Ciò significa che la coerenza delle query di lettura sarà la coerenza configurata per l'account.
- Nessuna: l'indicizzazione è disabilitata nel contenitore. Questa modalità viene comunemente usata quando un contenitore funge da archivio chiave-valore puro senza la necessità di indici secondari. Può essere usata anche per migliorare le prestazioni delle operazioni bulk. Al termine delle operazioni bulk, la modalità di indicizzazione può essere impostata su Coerente e quindi monitorata usando IndexTransformationProgress fino al completamento.
Nota
Azure Cosmos DB supporta anche una modalità di indicizzazione differita. L'indicizzazione differita esegue gli aggiornamenti dell'indice con un livello di priorità molto più basso quando il motore non esegue altre operazioni. Ciò può comportare risultati delle query incoerenti o incompleti. Se si prevede di eseguire una query su un contenitore Azure Cosmos DB, non è consigliabile selezionare l'indicizzazione differita. I nuovi contenitori non possono selezionare l'indicizzazione differita. È possibile richiedere un'esenzione contattando cosmosdbindexing@microsoft.com (tranne per i casi in cui si usa un account Azure Cosmos DB in modalità serverless che non supporta l'indicizzazione differita).
Per impostazione predefinita, i criteri di indicizzazione sono impostati su automatic
. Viene ottenuto impostando la proprietà automatic
dei criteri di indicizzazione su true
. L'impostazione di questa proprietà su true
consente ad Azure Cosmos DB di indicizzare automaticamente gli elementi durante la scrittura.
Dimensioni dell'indice
In Azure Cosmos DB lo spazio di archiviazione totale usato risulta dalla combinazione delle dimensioni dei dati e delle dimensioni dell'indice. Di seguito sono riportate alcune caratteristiche delle dimensioni dell'indice:
- Le dimensioni dell'indice dipendono dai criteri di indicizzazione. Se tutte le proprietà vengono indicizzate, le dimensioni dell'indice possono essere maggiori delle dimensioni dei dati.
- Quando i dati vengono eliminati, gli indici vengono compattati quasi continuamente. Tuttavia, per le eliminazioni di dati di piccole dimensioni, è possibile che non si osservi una diminuzione immediata delle dimensioni dell'indice.
- Le dimensioni dell'indice possono aumentare temporaneamente quando le partizioni fisiche vengono suddivise. Lo spazio di indice viene rilasciato una volta terminata la suddivisione della partizione.
Inclusione ed esclusione di percorsi delle proprietà
Un criterio di indicizzazione personalizzato può specificare i percorsi delle proprietà inclusi o esclusi in modo esplicito dall'indicizzazione. Ottimizzando il numero di percorsi indicizzati, è possibile ridurre notevolmente la latenza e l'addebito di UR per le operazioni di scrittura. Questi percorsi vengono definiti seguendo il metodo descritto nella sezione relativa alla panoramica dell'indicizzazione con le aggiunte seguenti:
- un percorso che conduce a un valore scalare (stringa o numero) termina con
/?
- gli elementi di una matrice vengono indirizzati insieme tramite la notazione
/[]
(invece di/0
,/1
e così via) - Il carattere jolly
/*
può essere usato per trovare le corrispondenze con qualsiasi elemento al di sotto del nodo
Riprendendo lo stesso esempio:
{
"locations": [
{ "country": "Germany", "city": "Berlin" },
{ "country": "France", "city": "Paris" }
],
"headquarters": { "country": "Belgium", "employees": 250 },
"exports": [
{ "city": "Moscow" },
{ "city": "Athens" }
]
}
il percorso
employees
diheadquarters
è/headquarters/employees/?
l percorso
country
dilocations
è/locations/[]/country/?
il percorso di qualsiasi elemento sotto
headquarters
è/headquarters/*
Ad esempio, è possibile includere il percorso /headquarters/employees/?
. Questo percorso garantisce l'indicizzazione della proprietà employees
, ma non indicizza codice JSON annidato aggiuntivo all'interno di questa proprietà.
Strategia di inclusione/esclusione
Qualsiasi criterio di indicizzazione deve includere il percorso radice /*
come percorso incluso o escluso.
Includere il percorso radice per escludere in modo selettivo i percorsi che non devono essere indicizzati. Questo approccio è consigliato perché consente ad Azure Cosmos DB di indicizzare in modo proattivo qualsiasi nuova proprietà che potrebbe essere aggiunta al modello.
Escludere il percorso radice per includere in modo selettivo i percorsi che devono essere indicizzati. Il percorso della proprietà della chiave di partizione non viene indicizzato per impostazione predefinita con la strategia di esclusione e deve essere incluso in modo esplicito, se necessario.
Per i percorsi con caratteri regolari che includono: caratteri alfanumerici e _ (carattere di sottolineatura), non è necessario eseguire l'escape della stringa di percorso accanto alle virgolette doppie (ad esempio, "/path/?"). Per i percorsi con altri caratteri speciali, è necessario eseguire l'escape della stringa di percorso accanto alle virgolette doppie (ad esempio "/"path-abc"/?"). Se nel percorso si prevedono caratteri speciali, è possibile eseguire l’escape di ogni percorso per sicurezza. Dal punto di vista funzionale, non fa alcuna differenza se si esegue l’escape di ogni percorso o solo di quelli con caratteri speciali.
La proprietà di sistema
_etag
viene esclusa dall'indicizzazione per impostazione predefinita, a meno che l'etag non venga aggiunto al percorso incluso per l'indicizzazione.Se la modalità di indicizzazione è impostata su coerente, le proprietà di sistema
id
e_ts
vengono indicizzate automaticamente.Se un percorso indicizzato in modo esplicito non esiste in un elemento, viene aggiunto un valore all'indice per indicare che il percorso non è definito.
Tutti i percorsi inclusi in modo esplicito hanno valori aggiunti all'indice per ogni elemento del contenitore, anche se il percorso non è definito per un determinato elemento.
Vedere questa sezione per consultare esempi di criteri di indicizzazione per includere ed escludere i percorsi.
Precedenza di inclusione/esclusione
Se i percorsi inclusi e i percorsi esclusi sono in conflitto, ha la precedenza il percorso più preciso.
Ecco un esempio:
Percorso incluso: /food/ingredients/nutrition/*
Percorso escluso: /food/ingredients/*
In questo caso, il percorso incluso ha la precedenza sul percorso escluso perché è più preciso. In base a questi percorsi, tutti i dati nel percorso food/ingredients
o annidati all'interno verrebbero esclusi dall'indice. L'eccezione è costituita dai dati all'interno del percorso incluso: /food/ingredients/nutrition/*
, che verrebbe indicizzato.
Ecco alcune regole per la precedenza dei percorsi inclusi ed esclusi in Azure Cosmos DB:
I percorsi più lunghi sono più precisi rispetto ai percorsi più brevi. ad esempio:
/a/b/?
è più preciso di/a/?
./?
è più preciso di/*
. Ad esempio,/a/?
è più preciso di/a/*
perciò/a/?
ha la precedenza.Il percorso
/*
deve essere un percorso incluso o un percorso escluso.
Indici full-text
Nota
Per specificare un indice full-text, è necessario abilitare la funzionalità di anteprima dell'API Full-Text e Ricerca ibrida per NoSQL.
Gli indici full-text consentono la ricerca full-text e l'assegnazione dei punteggi in modo efficiente usando l'indice. La definizione di un percorso full-text in un criterio di indicizzazione può essere eseguita facilmente includendo una fullTextIndexes
sezione dei criteri di indicizzazione che contiene tutti i percorsi di testo da indicizzare. Ad esempio:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/\"_etag\"/?"
},
],
"fullTextIndexes": [
{
"path": "/text"
}
]
}
Importante
Un criterio di indicizzazione full-text deve trovarsi nel percorso definito nei criteri full-text del contenitore. Altre informazioni sui criteri vettoriali dei contenitori.
Indici vettoriali
Nota
Per specificare un indice vettoriale, è necessario abilitare la funzionalità Ricerca vettoriale NoSQL di Azure Cosmos DB.
Gli indici vettoriali aumentano l'efficienza durante l'esecuzione di ricerche vettoriali usando la funzione di sistema VectorDistance
. Le ricerche vettoriali hanno una latenza inferiore, una velocità effettiva più elevata e un consumo minore di UR quando si applica un indice vettoriale. È possibile specificare i tipi seguenti di criteri di indice vettoriale:
Tipo | Descrizione | Dimensioni massime |
---|---|---|
flat |
Archivia i vettori nello stesso indice di altre proprietà indicizzate. | 505 |
quantizedFlat |
Quantizza (comprime) i vettori prima di archiviarli nell'indice. Ciò può migliorare la latenza e la velocità effettiva a scapito dell'accuratezza. | 4096 |
diskANN |
Crea un indice basato su DiskANN per una ricerca approssimativa veloce ed efficiente. | 4096 |
Importante
Attualmente, i criteri vettoriali e gli indici vettoriali non sono modificabili dopo la creazione. Per apportare modifiche, creare una nuova raccolta.
Alcuni punti da notare:
I tipi di indice
flat
equantizedFlat
applicano l'indice di Azure Cosmos DB per archiviare e leggere ogni vettore durante l'esecuzione di una ricerca vettoriale. Le ricerche vettoriali con un indiceflat
sono ricerche di forza bruta e producono precisione o richiamo al 100%. Ovvero, è garantito trovare i vettori più simili nel set di dati. Tuttavia, esiste una limitazione delle dimensioni505
per i vettori in un indice flat.L'indice
quantizedFlat
archivia i vettori quantizzati (compressi) nell'indice. Le ricerche vettoriali con indicequantizedFlat
sono anche ricerche di forza bruta, ma la loro accuratezza potrebbe essere leggermente inferiore al 100% perché i vettori vengono quantizzati prima di aggiungere all'indice. Tuttavia, le ricerche vettoriali conquantized flat
devono avere una latenza inferiore, una velocità effettiva più elevata e un costo UR inferiore rispetto alle ricerche vettoriali su un indiceflat
. Questa è un'opzione valida per gli scenari in cui si usano filtri di query per restringere la ricerca vettoriale a un set relativamente ridotto di vettori e è necessaria un'accuratezza elevata.L'indice
diskANN
è un indice separato definito in modo specifico per i vettori che applicano DiskANN, una suite di algoritmi di indicizzazione a vettori con prestazioni elevate sviluppati da Microsoft Research. Gli indici DiskANN possono offrire una certa latenza più bassa, la velocità effettiva più elevata e le query sui costi delle UR più basse, mantenendo comunque un'accuratezza elevata. Tuttavia, poiché DiskANN è un indice vicino più prossimo approssimativo (ANN), l'accuratezza potrebbe essere inferiore aquantizedFlat
oflat
.
Gli diskANN
indici e quantizedFlat
possono accettare parametri di compilazione dell'indice facoltativi che possono essere usati per ottimizzare l'accuratezza rispetto al compromesso di latenza applicabile a ogni indice di vettore Nearest Neighbors approssimativo.
quantizationByteSize
: imposta le dimensioni (in byte) per la quantizzazione del prodotto. Min=1, Default=dynamic (system decide), Max=512. L'impostazione di questa dimensione più grande può comportare ricerche di vettori di accuratezza più elevate a scapito di un costo più elevato delle UR e di una latenza più elevata. Questo vale sia per iquantizedFlat
DiskANN
tipi di indice che per i tipi di indice.indexingSearchListSize
: imposta il numero di vettori da cercare durante la costruzione della compilazione dell'indice. Min=10, Default=100, Max=500. L'impostazione di questo valore maggiore può comportare ricerche di vettori di accuratezza più elevati a scapito di tempi di compilazione più lunghi dell'indice e latenze di inserimento di vettori più elevati. Questo vale solo perDiskANN
gli indici.
Di seguito è riportato un esempio di criteri di indicizzazione con un indice vettoriale:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/_etag/?",
},
{
"path": "/vector/*"
}
],
"vectorIndexes": [
{
"path": "/vector",
"type": "diskANN"
}
]
}
Importante
I criteri di indicizzazione vettoriale devono trovarsi nel percorso definito nei criteri vettoriali del contenitore. Altre informazioni sui criteri vettoriali dei contenitori.
Importante
Percorso vettoriale aggiunto alla sezione "excludedPaths" dei criteri di indicizzazione per garantire prestazioni ottimizzate per l'inserimento. Se non si aggiunge il percorso vettoriale a "excludedPaths", l’addebito e la latenza delle RU risulteranno più elevati.
Indici spaziali
Quando si definisce un percorso spaziale nei criteri di indicizzazione, è necessario definire l'indice type
da applicare a tale percorso. Tra i possibili tipi di indici spaziali ci sono:
Point
Polygon
MultiPolygon
LineString
Azure Cosmos DB, per impostazione predefinita, non creerà indici spaziali. Se si desidera usare le funzioni predefinite spaziali di SQL, è necessario creare un indice spaziale nelle proprietà necessarie. Vedere questa sezione per consultare esempi di criteri di indicizzazione per l'aggiunta di indici spaziali.
Indici di tupla
Gli indici di tupla sono utili quando si esegue il filtro su più campi all'interno di un elemento di matrice. Gli indici di tupla vengono definiti nella sezione includedPaths dei criteri di indicizzazione usando l'identificatore di tupla "[]".
Nota
A differenza dei percorsi inclusi o esclusi, non è possibile creare un percorso con il carattere jolly /*. Ogni percorso di tupla deve terminare con "/?". Se una tupla in un percorso di tupla non esiste in un elemento, verrà aggiunto un valore all'indice per indicare che la tupla non è definita.
I percorsi di tupla di matrice verranno definiti nella sezione includedPaths e verranno usati la notazione seguente.
<path prefix>/[]/{<tuple 1>, <tuple 2> … <tuple n>}/?
Tenere presente quanto segue:
- La prima parte, il prefisso del percorso, è il percorso comune tra le tuple. È il percorso dalla radice alla matrice. Nell'esempio è "/events".
- Di seguito è riportato l'identificatore di caratteri jolly della matrice "[]". Tutti i percorsi della tupla di matrice devono avere un identificatore di caratteri jolly di matrice prima dell'identificatore di tupla "{}".
- Successivamente si specificano le tuple usando l'identificatore di tupla "{}".
- Le tuple saranno separate da virgole.
- La tupla deve usare la stessa specifica di percorso degli altri percorsi di indice con alcune eccezioni:
- Le tuple non devono iniziare con l'iniziale "/".
- Le tuple non devono contenere caratteri jolly di matrice.
- Le tuple non devono terminare "?" o "*"
- “?” è l'ultimo segmento in un percorso di tupla e deve essere specificato immediatamente dopo il segmento dell'identificatore di tupla.
ad esempio:
/events/[]/{name, category}/?
Di seguito sono riportati alcuni esempi di percorsi di tupla di matrice validi :
“includedPaths”:[
{“path”: “/events/[]/{name/first, name/last}/?”},
{“path”: “/events/[]/{name/first, category}/?”},
{“path”: “/events/[]/{name/first, category/subcategory}/?”},
{“path”: “/events/[]/{name/[1]/first, category}/?”},
{“path”: “/events/[]/{[1], [3]}/?”},
{“path”: “/city/[1]/events/[]/{name, category}/?”}
]
Di seguito sono riportati alcuni esempi di percorsi di tupla di matrici non validi
/events/[]/{name/[]/first, category}/?
- Una delle tuple ha un carattere jolly di matrice
/events/[]/{name, category}/*
- L'ultimo segmento nel percorso della tupla di matrice deve essere "?" e non *
/events/[]/{{name, first},category}/?
- L'identificatore di tupla è annidato
/events/{name, category}/?
- Il carattere jolly della matrice non è presente prima dell'identificatore di tupla
/events/[]/{/name,/category}/?
- Le tuple iniziano con l'inizio
/
- Le tuple iniziano con l'inizio
/events/[]/{name/?,category/?}/?
- Le tuple terminano con un
?
- Le tuple terminano con un
/city/[]/events/[]/{name, category}/?
- Prefisso del percorso come 2 caratteri jolly di matrice
Indici compositi
Le query che hanno una clausola ORDER BY
con due o più proprietà richiedono un indice composto. È possibile definire un indice composto anche per migliorare le prestazioni di molte query di uguaglianza e intervallo. Per impostazione predefinita, non sono definiti indici composti, pertanto è necessario aggiungere indici composti in base alle esigenze.
A differenza dei percorsi inclusi o esclusi, non è possibile creare un percorso con il carattere jolly /*
. Ogni percorso composto ha un implicito /?
alla fine del percorso, che non è necessario specificare. I percorsi composti portano a un valore scalare che è l'unico valore incluso nell'indice composto. Se un percorso di un indice composto non esiste in un elemento o porta a un valore non scalare, viene aggiunto un valore all'indice per indicare che il percorso non è definito.
Quando si definisce un indice composto, specificare:
Due o più percorsi delle proprietà. La sequenza in cui sono definiti i percorsi delle proprietà.
L’ordine (crescente o decrescente).
Nota
Quando si aggiunge un indice composto, la query utilizzerà gli indici di intervallo esistenti finché non viene completata l’aggiunta dell'indice composto. Pertanto, quando si aggiunge un indice composto, è possibile che non si osservino immediatamente miglioramenti delle prestazioni. È possibile tenere traccia dello stato di avanzamento della trasformazione dell'indice usando uno degli SDK.
Query ORDER BY su più proprietà:
Quando si usano indici compositi per le query con una ORDER BY
clausola con due o più proprietà, vengono usate le considerazioni seguenti.
Se i percorsi dell’indice composto non corrispondono alla sequenza delle proprietà nella clausola
ORDER BY
, l'indice composto non può supportare la query.Anche l'ordine dei percorsi dell’indice composto (crescente o decrescente) deve corrispondere a
order
nella clausolaORDER BY
.L'indice composto supporta anche una clausola
ORDER BY
con l'ordine opposto in tutti i percorsi.
Si consideri l'esempio seguente in cui viene definito un indice composto in base al nome, all'età e al _ts delle proprietà:
Indice composto | Query ORDER BY di esempio |
È supportata da un indice composto? |
---|---|---|
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age asc |
Yes |
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.age ASC, c.name asc |
No |
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.name DESC, c.age DESC |
Yes |
(name ASC, age ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age DESC |
No |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age ASC, timestamp ASC |
Yes |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c ORDER BY c.name ASC, c.age ASC |
No |
È consigliabile personalizzare i criteri di indicizzazione in modo da poter gestire tutte le query ORDER BY
necessarie.
Query con filtri su più proprietà
Se una query ha filtri su due o più proprietà, potrebbe essere utile creare un indice composto per queste proprietà.
Si consideri, ad esempio, la query seguente con un filtro di uguaglianza e di intervallo:
SELECT *
FROM c
WHERE c.name = "John" AND c.age > 18
Questa query è più efficiente, richiederà meno tempo e meno UR, se è in grado di applicare un indice composto in (name ASC, age ASC)
.
Le query con più filtri di intervallo possono essere ottimizzate anche con un indice composto. Tuttavia, ogni singolo indice composto può ottimizzare solo un singolo filtro di intervallo. I filtri di intervallo includono >
, <
, <=
, >=
e !=
. Il filtro di intervallo deve essere definito come ultimo nell'indice composto.
Si consideri la query seguente con un filtro di uguaglianza e due filtri di intervallo:
SELECT *
FROM c
WHERE c.name = "John" AND c.age > 18 AND c._ts > 1612212188
Questa query è più efficiente con un indice composto su (name ASC, age ASC)
e (name ASC, _ts ASC)
. Tuttavia, la query non utilizzerebbe un indice composto su (age ASC, name ASC)
perché le proprietà con filtri di uguaglianza devono essere definite come prime nell'indice composto. Sono necessari due indici composti separati anziché un singolo indice composto su (name ASC, age ASC, _ts ASC)
perché ogni indice composto può ottimizzare solo un singolo filtro di intervallo.
Quando si creano indici composti per le query con filtri su più proprietà, vengono applicate le considerazioni seguenti
- Le espressioni filtro possono usare più indici composti.
- Le proprietà del filtro della query devono corrispondere a quelle dell'indice composto. Se una proprietà si trova nell'indice composto ma non è inclusa nella query come filtro, la query non utilizzerà l'indice composto.
- Se una query ha altre proprietà nel filtro che non sono definite in un indice composto, viene usata una combinazione di indici composti e di intervallo per valutare la query. Questo richiede meno UR rispetto all'uso esclusivo degli indici di intervallo.
- Se una proprietà ha un filtro di intervallo (
>
,<
,<=
,>=
o!=
), questa proprietà deve essere definita come ultima nell'indice composto. Se una query dispone di più filtri di intervallo, potrebbe trarre vantaggio da più indici composti. - Quando si crea un indice composto per ottimizzare le query con più filtri, il
ORDER
dell'indice composto non ha alcun impatto sui risultati. Questa proprietà è facoltativa.
Si considerino gli esempi seguenti in cui viene definito un indice composto in base al nome, all'età e al timestamp delle proprietà:
Indice composto | Query di esempio | È supportata da un indice composto? |
---|---|---|
(name ASC, age ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age = 18 |
Yes |
(name ASC, age ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age > 18 |
Yes |
(name ASC, age ASC) |
SELECT COUNT(1) FROM c WHERE c.name = "John" AND c.age > 18 |
Yes |
(name DESC, age ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age > 18 |
Yes |
(name ASC, age ASC) |
SELECT * FROM c WHERE c.name != "John" AND c.age > 18 |
No |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age = 18 AND c.timestamp > 123049923 |
Yes |
(name ASC, age ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age < 18 AND c.timestamp = 123049923 |
No |
(name ASC, age ASC) and (name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.age < 18 AND c.timestamp > 123049923 |
Yes |
Query con un filtro e ORDER BY
Se una query filtra una o più proprietà e ha proprietà diverse nella clausola ORDER BY, potrebbe essere utile aggiungere le proprietà del filtro alla clausola ORDER BY
.
Ad esempio, aggiungendo le proprietà del filtro alla clausola ORDER BY
, è possibile riscrivere la query seguente per applicare un indice composto:
Eseguire una query usando l'indice di intervallo:
SELECT *
FROM c
WHERE c.name = "John"
ORDER BY c.timestamp
Eseguire una query usando l'indice composto:
SELECT *
FROM c
WHERE c.name = "John"
ORDER BY c.name, c.timestamp
Le stesse ottimizzazioni query possono essere generalizzate per qualsiasi query ORDER BY
con filtri, tenendo presente che i singoli indici composti possono supportare al massimo un filtro di intervallo.
Eseguire una query usando l'indice di intervallo:
SELECT *
FROM c
WHERE c.name = "John" AND c.age = 18 AND c.timestamp > 1611947901
ORDER BY c.timestamp
Eseguire una query usando l'indice composto:
SELECT *
FROM c
WHERE c.name = "John" AND c.age = 18 AND c.timestamp > 1611947901
ORDER BY c.name, c.age, c.timestamp
Inoltre, è possibile usare indici composti per ottimizzare le query con funzioni di sistema e ORDER BY:
Eseguire una query usando l'indice di intervallo:
SELECT *
FROM c
WHERE c.firstName = "John" AND Contains(c.lastName, "Smith", true)
ORDER BY c.lastName
Eseguire una query usando l'indice composto:
SELECT *
FROM c
WHERE c.firstName = "John" AND Contains(c.lastName, "Smith", true)
ORDER BY c.firstName, c.lastName
Quando si creano indici composti per ottimizzare una query con un filtro e una clausola ORDER BY
, si applicano le considerazioni seguenti:
- Se non si definisce un indice composto in una query con un filtro su una proprietà e una clausola
ORDER BY
separata usando una proprietà diversa, la query avrà comunque esito positivo. Tuttavia, il costo UR della query può essere ridotto con un indice composto, in particolare se la proprietà della clausolaORDER BY
ha una cardinalità elevata. - Se la query filtra le proprietà, queste proprietà devono essere incluse per prime nella clausola
ORDER BY
. - Se la query filtra più proprietà, i filtri di uguaglianza devono essere le prime proprietà della clausola
ORDER BY
. - Se la query filtra più proprietà, è possibile avere un massimo di un filtro di intervallo o una funzione di sistema utilizzati per ogni indice composto. La proprietà utilizzata nel filtro di intervallo o nella funzione di sistema deve essere definita per ultima nell'indice composto.
- Tutte le considerazioni per la creazione di indici composti per le query
ORDER BY
con più proprietà e le query con filtri su più proprietà sono comunque valide.
Indice composto | Query ORDER BY di esempio |
È supportata da un indice composto? |
---|---|---|
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" ORDER BY c.name ASC, c.timestamp ASC |
Yes |
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" AND c.timestamp > 1589840355 ORDER BY c.name ASC, c.timestamp ASC |
Yes |
(timestamp ASC, name ASC) |
SELECT * FROM c WHERE c.timestamp > 1589840355 AND c.name = "John" ORDER BY c.timestamp ASC, c.name ASC |
No |
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" ORDER BY c.timestamp ASC, c.name ASC |
No |
(name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.name = "John" ORDER BY c.timestamp ASC |
No |
(age ASC, name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.age = 18 and c.name = "John" ORDER BY c.age ASC, c.name ASC,c.timestamp ASC |
Yes |
(age ASC, name ASC, timestamp ASC) |
SELECT * FROM c WHERE c.age = 18 and c.name = "John" ORDER BY c.timestamp ASC |
No |
Query con un filtro e un'aggregazione
Se una query filtra una o più proprietà e ha una funzione di sistema di aggregazione, potrebbe essere utile creare un indice composto per le proprietà nella funzione di sistema di filtro e aggregazione. Questa ottimizzazione si applica alle funzioni di sistema SUM e AVG.
Quando si creano indici composti per ottimizzare una query con una funzione di sistema di filtro e aggregazione, si applicano le considerazioni seguenti.
- Gli indici composti sono facoltativi quando si eseguono query con aggregazioni. Tuttavia, il costo UR della query spesso può essere ridotto con un indice composto.
- Se la query filtra più proprietà, i filtri di uguaglianza devono essere le prime proprietà dell'indice composto.
- È possibile avere un massimo di un filtro di intervallo per indice composto e questo deve trovarsi nella proprietà nella funzione di sistema di aggregazione.
- La proprietà della funzione di sistema di aggregazione deve essere definita per ultima nell'indice composto.
- L'oggetto
order
(ASC
oDESC
) non è importante.
Indice composto | Query di esempio | È supportata da un indice composto? |
---|---|---|
(name ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" |
Yes |
(timestamp ASC, name ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" |
No |
(name ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name > "John" |
No |
(name ASC, age ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" AND c.age = 25 |
Yes |
(age ASC, timestamp ASC) |
SELECT AVG(c.timestamp) FROM c WHERE c.name = "John" AND c.age > 25 |
No |
Indici compositi con un carattere jolly di matrice
Di seguito è riportato un esempio per un indice composito che contiene un carattere jolly di matrice.
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{
"path":"/*"
}
],
"excludedPaths":[],
"compositeIndexes":[
[
{"path":"/familyname", "order":"ascending"},
{"path":"/children/[]/age", "order":"descending"}
]
]
}
Una query di esempio che può trarre vantaggio da questo indice composito è:
SELECT r.id
FROM root r
JOIN ch IN r.children
WHERE r.familyname = 'Anderson' AND ch.age > 20
Modifica dei criteri di indicizzazione
I criteri di indicizzazione di un contenitore possono essere aggiornati in qualsiasi momento usando il portale di Azure o uno degli SDK supportati. L’aggiornamento dei criteri di indicizzazione attiva una trasformazione dall'indice precedente in uno nuovo, che viene eseguita online e sul posto (pertanto non viene utilizzato ulteriore spazio di archiviazione durante l'operazione). I criteri di indicizzazione precedenti vengono trasformati in modo efficiente nei nuovi criteri senza influire sulla disponibilità di scrittura, sulla disponibilità in lettura o sulla velocità effettiva di cui è stato effettuato il provisioning nel contenitore. La trasformazione dell’indice è un'operazione asincrona e il tempo necessario per il suo completamento dipende dalla velocità effettiva con provisioning, dal numero di elementi e dalle relative dimensioni. Se è necessario apportare più aggiornamenti ai criteri di indicizzazione, è consigliabile eseguire tutte le modifiche come singola operazione per completare la trasformazione dell'indice il più rapidamente possibile.
Importante
La trasformazione Indice è un'operazione che utilizza le unità richiesta e l'aggiornamento dei criteri di indice è un'operazione associata alle UR. Se un termine di indicizzazione non viene eseguito, il cliente visualizzerà le query che utilizzano unità richiesta più complessive.
Nota
È possibile tenere traccia dello stato di avanzamento della trasformazione dell'indice nel portale di Azure o usando uno degli SDK.
Non c'è alcun impatto sulla disponibilità di scrittura durante qualsiasi trasformazione dell'indice. La trasformazione dell'indice usa le UR di cui è stato effettuato il provisioning, ma con una priorità inferiore rispetto alle operazioni CRUD o alle query.
Non c'è alcun impatto sulla disponibilità di lettura quando si aggiungono nuovi percorsi indicizzati. Le query utilizzeranno nuovi percorsi indicizzati solo una volta completata la trasformazione di un indice. In altre parole, quando si aggiunge un nuovo percorso indicizzato, le query che traggono vantaggio da tale percorso indicizzato hanno le stesse prestazioni prima e durante la trasformazione dell'indice. Al termine della trasformazione dell'indice, il motore di query inizierà a usare i nuovi percorsi indicizzati.
Quando si rimuovono i percorsi indicizzati, è necessario raggruppare tutte le modifiche in un'unica trasformazione dei criteri di indicizzazione. Se si rimuovono più indici e si esegue questa operazione in un unico criterio di indicizzazione, il motore di query fornisce risultati coerenti e completi durante la trasformazione dell'indice. Tuttavia, se si rimuovono gli indici tramite più operazioni di modifica dei criteri di indicizzazione, il motore di query non fornirà risultati coerenti o completi fino al completamento di tutte le trasformazioni dell'indice. La maggior parte degli sviluppatori non elimina gli indici e quindi prova immediatamente a eseguire query che usano questi indici, quindi, questa situazione è praticamente improbabile.
Quando si elimina un percorso indicizzato, il motore di query smetterà immediatamente di usarlo e eseguirà invece un'analisi completa.
Nota
Se possibile, si dovrebbe sempre cercare di raggruppare più rimozioni di indice in un unico criterio di indicizzazione.
Importante
La rimozione di un indice ha effetto immediato, mentre l'aggiunta di un nuovo indice richiede del tempo perché richiede una trasformazione di indicizzazione. Quando si sostituisce un indice con un altro (ad esempio, sostituendo un singolo indice di proprietà con un indice composito), assicurarsi di aggiungere prima il nuovo indice e quindi attendere che la trasformazione dell'indice sia completa prima di rimuovere l'indice precedente dai criteri di indicizzazione. In caso contrario, ciò influirà negativamente sulla possibilità di eseguire una query sull'indice precedente e potrebbe interrompere eventuali carichi di lavoro attivi che fanno riferimento all'indice precedente.
Criteri di indicizzazione e TTL
L'uso della funzionalità TTL (Time-to-Live) richiede l'indicizzazione. Ciò significa che:
- non è possibile attivare il TTL in un contenitore in cui la modalità di indicizzazione è impostata su
none
, - non è possibile impostare la modalità di indicizzazione su Nessuna in un contenitore in cui è attivato il TTL.
Per gli scenari in cui non è necessario indicizzare alcun percorso di proprietà, ma è richiesto il TTL, è possibile usare un criterio di indicizzazione con una modalità di indicizzazione impostata su consistent
, nessun percorso incluso e /*
come unico percorso escluso.