2016-01-11 11 views
6

La guida elasticsearch diceelasticsearch: Ordine dei filtri per la migliore prestazione

"Ogni filtro viene calcolato e memorizzato nella cache in modo indipendente, a prescindere da dove viene utilizzato Se due query diverse utilizzano lo stesso filtro, lo stesso bitset filtro. verrà riutilizzato, allo stesso modo, se una singola query utilizza lo stesso filtro in più punti, viene calcolato solo un bit set e quindi riutilizzato. " (https://www.elastic.co/guide/en/elasticsearch/guide/current/filter-caching.html)

in un'altra pagina si legge anche:

"L'ordine dei filtri in una clausola bool è importante per le prestazioni dei filtri più specifici devono essere collocati prima di filtri meno specifici. per escludere il maggior numero possibile di documenti, il prima possibile: se la clausola A potrebbe corrispondere a 10 milioni di documenti e la clausola B potrebbe corrispondere solo a 100 documenti, allora la clausola B dovrebbe essere posta prima della clausola A. " (https://www.elastic.co/guide/en/elasticsearch/guide/current/_filter_order.html)

io non capisco come l'ordine dei filtri in una clausola bool è importante quando ogni filtro viene memorizzato nella cache in modo indipendente.

Immagino che la clausola B sia eseguita o recuperata dalla cache, il paragrafo A sia eseguito o recuperato dalla cache e quindi i bitset del filtro siano "uniti". Perché l'ordine è importante?

risposta

11

Questa guida è un po 'fuorviante. È più complicato ed è molto difficile provare a scrivere una serie di regole che si adattino a tutte le situazioni. Quando i dati cambiano, le regole cambiano. Man mano che cambiano i tipi di query e di filtro, le regole cambiano. Un filtro specifico potrebbe essere più lento da eseguire rispetto a uno ampio, le regole cambiano. Su una base per segmento, la dimensione del risultato di un filtro potrebbe essere opposta rispetto a quella di un altro segmento, non è sempre prevedibile. Quindi, per prima cosa devi capire più dettagli interni, quindi devi lasciar andare cercando di controllarlo mentre ti muovi nella moderna Elasticsearch 2.x.

NOTA:vostra seconda citazione (ordine del filtro) e collegamento associato è quello di una pagina che è considerato "fuori data" per elasticsearch 2.x, sarà aggiornato in seguito. Pertanto il consiglio può o non può applicarsi ai tempi moderni.

Guardando indietro nel tempo per elasticsearch 1.x e il motivo per il suggerimento ordinazione:

Parliamo prima di come i filtri sono rappresentati in memoria. Si tratta di una lista iterata di documenti corrispondenti o di un modello di "accesso casuale". A seconda del tipo di filtro, dipende da quale è più efficiente.Ora se tutto è memorizzato nella cache, li stai solo intersecando e il costo varierà in base alla dimensione e al tipo.

Se i filtri non vengono memorizzate, ma sono cacheable poi un filtro eseguirà indipendentemente ed i filtri precedenti influenzerà solo dal costo complessivo di intersezione.

Se il filtro non è cacheable allora potrebbe essere guidata dai risultati precedenti. Immagina uno Query più uno Filter. Se esegui la query e dopo aver applicato il filtro, stai facendo molto lavoro extra se il filtro limita a un set molto piccolo di record. Hai perso tempo nella query con la raccolta, il punteggio e la creazione di una serie di risultati complessivi. Ma se si converte a un FilteredQuery e fare entrambe le cose allo stesso tempo, allora la Query ignora tutti i record già eliminati dal Filter. Basta considerare gli stessi documenti già in gioco. Questo è chiamato "saltare". Non tutti i tipi di filtro sfruttano il salto, ma alcuni possono. Ed è per questo che un filtro "guida" più piccolo farà sì che gli altri lo usino più velocemente.

A meno che non si conosca ciascun tipo di filtro, l'euristica dei dati e in che modo ciascun filtro specifico sarà interessato da ciascuno di questi, non si dispone di informazioni sufficienti per dire solo "inserire prima la maggior parte dei filtri limitati e quelli più grandi second " e spero che funzioni. Per bool l'impostazione predefinita non è memorizzare nella cache il risultato complessivo in modo da prestare attenzione alle sue prestazioni ripetute (e/o memorizzarlo nella cache). È più efficiente quando un lato dell'intersezione del filtro è piccolo. Quindi, avere un piccolo inizio, rende più veloci tutte le altre intersezioni perché possono ridursi. Se si trattasse di una query bool invece di un filtro di facendo segnare è ancora più importante per evitare segnando più documenti del necessario.

Un'altra nota importante è che "filtro più specifico prima" a volte può essere lenta (filtro di script, o altro), in modo che in realtà dovrebbe leggere: "più basso costo, filtri più specifici primi".

Con Elasticsearch 2.0, things will change:

È il momento di dimenticare tutto ciò che sapeva sulle query e filtri: elasticsearch 2.0 prendere decisioni molto meglio da sola, invece di affidarsi agli utenti di formulare una query ottimizzata.

In 2.x dovresti provare meno a giocare al sistema e lasciare che il motore faccia le scelte migliori. In realtà il motore potrebbe finire con qualcosa di molto diverso sotto il cofano, un filtro riscritto, un cambiamento completo nella struttura interna e nei dati. E potresti anche non controllare più il caching. Quindi devi leggere di più a riguardo.

Il precedente API di filtro potrebbe essere consumati in due modi: o utilizzando iteratori i documenti corrispondenti, oppure utilizzando un'API ad accesso casuale opzionale che ha permesso di verificare se un particolare documento abbinato al filtro oppure no. Tutto è bene finora, salvo che il modo migliore per consumare un filtro dipendeva quale tipo di filtro si ha: per esempio il filtro script era più efficiente quando si utilizza l'API di accesso casuale mentre il filtro bool era più efficiente utilizzando l'API iteratore . Questo era piuttosto un incubo per ottimizzare e fu la causa principale per cui il filtro bool da un lato e le and e or filtri dall'altro Dinamiche diverse.

Il motore ora deciderà cosa è meglio prendere in considerazione più fattori tra cui il punteggio, la stima della dimensione del risultato, il modo migliore per intersecare i filtri correlati, magari anche su base per segmento, e altro ancora.

Anche questo articolo chiarisce che anche il caching può essere fuorviante, non sempre rende le cose più veloci. A volte una struttura di dati interna è migliore quando originariamente utilizzata, rispetto alla struttura bitset che viene sempre memorizzata nella cache. Così anche in 2.x questo sta cambiando per evitare di memorizzare nella cache cose che si eseguono meglio dalla struttura di dati nativi senza memorizzare nella cache.

Nel post del blog Roaring Bitmaps sono ulteriori dettagli:

Chiaramente il requisito più importante è avere qualcosa di veloce: se il filtro nella cache è più lento di esecuzione nuovamente il filtro, non è solo consumando memoria, ma anche rendendo le tue domande più lente. Il più sofisticato una codifica è, il più probabile è quello di rallentare la codifica e la decodifica a causa del maggiore utilizzo della CPU

Qui si ottiene un sacco di informazioni circa le strutture dati interne, caching, intersezione e più sulla modifiche interne in 2.x che ti aiuteranno ad avere una maggiore comprensione delle prestazioni del filtro.

Anche se può sorprendere se siete nuovi per la ricerca interni del motore, uno dei più importanti elementi costitutivi di un motore di ricerca è la capacità di comprimere in modo efficiente e decodificare liste ordinate di interi in fretta.

Da questi ultimi due link di blog 2.x hai un sacco di informazioni sulla tua domanda, parlano di tutti i problemi che stai cercando di aggirare con l'ordinamento dei filtri. Le informazioni e i dettagli sono tutti lì e puoi avere una migliore comprensione di 1.x contro 2.x e di come le query + i filtri sono risolti. Quindi ricorda:

Non esiste un'implementazione particolare che sia costantemente migliore di tutte le altre.

Vedi anche queste risorse 1.x di riferimento storico:

  • Optimizing Elasticsearch searches copre un po 'di più su ordinazione del filtro. In sintesi:

    Detto questo, è ancora necessario pensare a quale ordine si filtra. Si desidera che i filtri più selettivi vengano eseguiti per primi. Supponi di filtrare sul tipo: libro e tag: elasticsearch. Se hai 30 milioni di documenti, 10 milioni di libri di testo e solo 10 taggati Elasticsearch, ti consigliamo di applicare prima il filtro dei tag. Riduce il numero di documenti molto più del filtro del libro.

  • All About Elasticsearch Filter Bitsets è considerato un articolo obsoleto per i tempi moderni, ma dà più di fondo sul documento filtro di ordine che hai citato.

  • A forum answer by Martijn v Groningen sembra dire il contrario di bool rispetto a and query su cui viene utilizzata l'iterazione vs.accesso casuale, ma l'idea è la stessa per ciascuno: sii sicuro limitando i documenti in precedenza nell'elenco dei filtri, indipendentemente dal modello utilizzato per un tipo rispetto all'altro.

+1

Jayson, grazie per il tempo dedicato a questa risposta – Ronald

-1

Immagino che sia più efficiente unire un set più piccolo di documenti corrispondenti al set più grande, o operare in questo ordine dà una maggiore possibilità di azzeramento delle corrispondenze e quindi è possibile prendere scorciatoie. Avrebbe bisogno di controllare il codice sorgente (Elasticsearch e Lucene) per sapere con certezza.

mi corregga se sbaglio ...

1

Non tutti i filtri vengono memorizzati nella cache/cacheable. Ad esempio, un filtro dell'intervallo di date che utilizza la variabile now non viene memorizzato nella cache perché cambia continuamente. se si guarda un po 'più in basso nel primo link che hai dato, si vedrà una sezione denominata "Controlling caching", in cui si afferma questo fatto:

Alcuni filtri foglia, tuttavia, non sono memorizzati nella cache per impostazione predefinita, perché doesn' ha senso farlo: filtri di script, filtri geografici, filtri di intervalli di date.

Per illustrare questo, diciamo che abbiamo la seguente filtro data range (chiamiamolo filtro A) che filtra tutti i documenti del mese scorso

"range" : { 
    "timestamp" : { 
     "gt" : "now-1m" 
    } 
} 

e un altro filtro term (chiamiamola filtro B) per filtrare i documenti con il tipo XYZ

"term" : { 
    "type" : "XYZ" 
} 

si fa una grande differenza (prestazioni saggio) se si inserisce

  1. filtro A prima del filtro B o
  2. filtro B prima filtro A

Nel caso 1, l'esecuzione sarà più lenta, perché tutti i documenti del mese scorso sarà necessario passare attraverso il filtro Una prima , che non è memorizzato nella cache.

Nel caso 2, si filtrano prima tutti i documenti senza lo typeXYZ, che è veloce perché il filtro B è memorizzato nella cache. Quindi i documenti che sono passati attraverso il filtro B possono passare attraverso il filtro A. Quindi, anche se il filtro A non è memorizzato nella cache, l'esecuzione sarà comunque più veloce poiché nella pipeline del filtro sono rimasti meno documenti.

Questo è stato un esempio molto semplice, ma dovrebbe mostrare perché l'ordine del filtro è importante, ovvero principalmente perché alcuni filtri non sono memorizzati nella cache. È possibile modificare tale comportamento predefinito forzando la memorizzazione nella cache, ma a volte non è una buona idea. La migliore pratica consiste nell'applicare i filtri più aggressivi prima in modo da lasciare passare il minor numero di documenti possibile attraverso il filtro successivo.

Personalmente lo chiamo "l'approccio del bulldozer", cioè prima assicurati di elaborare quanto più materiale possibile il più presto possibile nella pipeline del filtro, e alla fine si finisce con una porzione di dati più masticabile che può essere elaborata più veloce.

+0

Ciao Val, innanzitutto grazie per la tua risposta elaborata. Ero consapevole dello scenario che descrivi. Per me questa è fondamentalmente la seconda parte di https://www.elastic.co/guide/en/elasticsearch/guide/current/_filter_order.html che inizia con "I filtri cache sono molto veloci, quindi devono essere posizionati prima dei filtri che non sono memorizzabili nella cache. " Ma la prima parte di questa pagina dice "I filtri più specifici devono essere posizionati prima di filtri meno specifici al fine di escludere il maggior numero possibile di documenti, il prima possibile". – Ronald

+0

Non dice "I filtri memorizzabili in cache devono essere posizionati prima dei filtri non intercambiabili per escludere quanti più documenti possibile, il prima possibile." E dà anche un esempio di due filtri con una quantità fissa di documenti ciascuno - quindi entrambi sembrano essere intercambiabili. "Se la clausola A potrebbe corrispondere a 10 milioni di documenti e la clausola B potrebbe corrispondere solo a 100 documenti, allora la clausola B dovrebbe essere posta prima della clausola A." Se ognuno di questi filtri viene calcolato e memorizzato nella cache in modo indipendente, non vedo perché l'ordine è importante. – Ronald

+0

Ma forse sto leggendo molto e ci vogliono solo dirci mettere filtri intercambiabili prima dei filtri non intercambiabili. – Ronald

0

questo blog post on elastic website postato maggio 2017 dice

D: l'ordine in cui ho messo le mie domande/filtri nella query DSL importa?

A: No, perché saranno automaticamente riordinati in ogni caso in base ai rispettivi costi e costi di corrispondenza.

Problemi correlati