MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Indice Mongo triplo composto

riga in basso / tl;dr: Indice b può essere 'saltato' se a e c vengono interrogati per l'uguaglianza o la disuguaglianza, ma non, ad esempio, per gli ordinamenti su c .

Questa è un'ottima domanda. Sfortunatamente, non sono riuscito a trovare nulla che risponda in modo autorevole a questo in modo più dettagliato. Credo che le prestazioni di tali query siano migliorate negli ultimi anni, quindi non mi fiderei del vecchio materiale sull'argomento.

L'intera faccenda è piuttosto complicata perché dipende dalla selettività dei tuoi indici e dal fatto che tu esegua una query per uguaglianza, disuguaglianza e/o ordinamento, quindi explain() è il tuo unico amico, ma ecco alcune cose che ho trovato:

Avvertimento :Quello che arriva ora è un misto di risultati sperimentali, ragionamenti e supposizioni. Potrei esagerare con l'analogia di Kyle e potrei anche sbagliarmi completamente (e sfortunato, perché i risultati dei miei test corrispondono vagamente al mio ragionamento).

È chiaro che può essere utilizzato l'indice di A che, a seconda della selettività di A, è sicuramente molto utile. "Saltare" B può essere complicato o meno. Manteniamo questo simile all'esempio del libro di cucina di Kyle:

French
    Beef
        ...
    Chicken
        Coq au Vin
        Roasted Chicken
    Lamb
        ...
    ...

Se ora mi chiedi di trovare qualche piatto francese chiamato "Chateaubriand", posso usare l'indice A e, poiché non conosco l'ingrediente, dovrò scansionare tutti i piatti in A . D'altra parte, so che l'elenco dei piatti di ogni categoria è ordinato tramite l'indice C , quindi dovrò solo cercare le stringhe che iniziano con, diciamo, "Cha" in ogni lista di ingredienti. Se ci sono 50 ingredienti, avrò bisogno di 50 ricerche invece di una sola, ma è molto meglio che dover scansionare ogni piatto francese!

Nei miei esperimenti, il numero era molto più piccolo del numero di valori distinti in b :non sembrava mai superare 2. Tuttavia, l'ho testato solo con una singola raccolta e probabilmente ha a che fare con la selettività del b -indice.

Se mi chiedessi di darti un elenco in ordine alfabetico di tutti i piatti francesi , tuttavia, sarei nei problemi . Ora l'indice su C è inutile, dovrei unire-ordinare tutti quegli elenchi di indici. Dovrò scansionare ogni elemento per farlo.

Questo si riflette nei miei test. Ecco alcuni risultati semplificati. La raccolta originale ha datetime, int e stringhe, ma volevo mantenere le cose semplici, quindi ora è tutto ints.

In sostanza, ci sono solo due classi di query:quelle in cui nscanned <=2 * limit e quelli che devono scansionare l'intera collezione (120.000 documenti). L'indice è {a, b, c} :

// fast (range query on c while skipping b)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }});
// slow (sorting)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1});
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1}); 

// fast (can sort on c if b included in the query)
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1});

// fast (older tutorials claim this is slow)
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }});

Il tuo chilometraggio varierà.