Knowledge Base - MongoDB¶
- Table of contents
- Knowledge Base - MongoDB
- Cold dotazy jsou drahe stoji hodne casu, nasledujici hot dotazy jsou uz pak rychle
- Zvlastni chovani Monga pri vyberu vsech polozek (rychlejsi odpoved) vs. jen poslednich X stranek pomoci SKIP LIMIT (pomalejsi odpoved)
- Vidíme že vo väčšine prípadov trvá vyčítanie len poslednej stránky výrazne dlhšie ako vyčítanie celej množiny.
- Jediný prípad kde sa to nedeje je HAWAT3, čo je obmedzenie len na čas a kategóriu.
- Pri väčšom množstve vrátených záznamov už je použitie SKIP+LIMIT efektívnejšie ako prečítanie celého súboru, ale rozdiel je v podstate príliš malý (pri HAWAT1: ~73s celý súbor, ~60s len posledná stránka).
- Podľa explain() je rozdiel v tom, že pri HAWAT3 sa aplikuje SKIP fáza s nenulovou hodnotou (skok asi do polovice tabuľky), zatiaľ čo napr. u HAWAT1 je to 0 a teda sú vyčítané dokumenty od začiatku.
- TS3.2 predpokladateľne ukazuje, že opačné radenie dotaz mierne spomalí. To vyzerá byť konzistentné naprieč dotazmi aj variantami dotazovania.
- Pozor na pole a relační operátory. Dotaz X > 3 and X < 8 matchne i pole X = [2, 9], protože v X je alespoň jedna položka menší, než 8 (2), a alespoň jedna větší, než 3 (9). Je potřeba použít $elemMatch, viz také #3045.
Indexy¶
- Je důležité dostat indexy Monga do paměti, to je první výkonová bariéra
- Mohou pomoci sparse indexy, které indexují jen existující pole (https://docs.mongodb.com/manual/core/index-sparse/)
- V dokumentaci je zmíněno, že Mongo může udržovat v paměti jen hot část indexu, ale nevíme, zda aktivně, či to prostě nechává na OS (https://docs.mongodb.com/manual/tutorial/ensure-indexes-fit-ram/#indexes-that-hold-only-recent-values-in-ram)
- Selektivní index - indexovat primárně podle polí, která u obvyklých dotazů vyberou nejmenší počet výsledků (https://docs.mongodb.com/manual/tutorial/create-queries-that-ensure-selectivity/)
- Platí i pro složené indexy - pořadí polí podle selektivity
- Za nějakých okolností může Mongo použít průnik indexů (https://docs.mongodb.com/manual/core/index-intersection/), ale ještě jsem to nepotkal
- Nelze použít, pokud sort vyžaduje jiný index, než je použit v predikátech (https://docs.mongodb.com/manual/core/index-intersection/#index-intersection-compound-indexes)
- Používat projekci, tj. jen zajímavá pole, lze dosáhnout covered query (splnění pouze z indexu) (https://docs.mongodb.com/manual/tutorial/optimize-query-performance-with-indexes-and-projections/#use-projections-to-return-only-necessary-data)
- Multikey index, tj. index na pole, nemůže být covered, tj. Mongo bude muset vždy do dat (https://docs.mongodb.com/manual/core/query-optimization/#covered-query)
Indexy a řazení¶
- https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/
- Umí použít index k řazení, pokud sort key je prefixem použitého indexu (index nad a, nebo a-b)
- db.data.find( { a: { $gt: 1234 }, b: { $gt: 5678 } } ).sort({a: -1})
- Použití indexu pro řazení v opačném směru je méně efektivní
- Pokud sort key není prefixem, údajně musí být suffix a predikáty prefix, ale to funguje jen pokud predikáty jsou exaktní (ne range/multivalue dotaz), a pokud případný range dotaz je pouze na sortkey
- db.data.find( { a: 5 } ).sort( { b: 1, c: 1 } ) # index { a: 1 , b: 1, c: 1 }
- db.data.find( { b: 3, a: 4 } ).sort( { c: 1 } ) # index { a: 1, b: 1, c: 1 }
- db.data.find( { a: 5, b: { $lt: 3} } ).sort( { b: 1 } ) # index { a: 1, b: 1 }
Efektivita indexů¶
- https://docs.mongodb.com/manual/reference/operator/aggregation/indexStats/#pipe._S_indexStats
- https://docs.mongodb.com/manual/tutorial/measure-index-use/
Návrh indexu (shrnutí ze zkušeností)¶
Compound index pro konkrétní query by měl být složen takto:
- eqA, eqB, eqC, ... , sortkeyA, sortkeyB, multiA, multiB, ...
Kde:
- eqX jsou predikáty absolutního porovnání nad single položkou
- tj. např. {'a': 3}, nebo {'a' : { '$eq': 3}}
- a nesmí být pole
- sortkeyX - řadící klíče, ve správném směru
- tedy např. find(...).sort({sortkeyA:1, sortkeyB:-1, sortkeyC:-1})
- součástí query mohou být range ($lt, $gt) queries na sortkey
- multiX - cokoliv, co vrací víc výsledků - range query, $in, $eq na pole, atd.
- je třeba vzít v úvahu, že v klíči může být současně jen jedno pole
- ale mohou tam být dvě položky, které jsou součástí jednoho pole, např. je-li 'a' pole, pak index {a.X: 1, a.Y: 1} je ok
Ladění¶
Explain¶
- https://docs.mongodb.com/manual/reference/explain-results/
- https://2guysfrommumbai.wordpress.com/2013/10/13/mongodb-understanding-your-queries-through-explainplan/
- https://docs.mongodb.com/manual/tutorial/analyze-query-plan/
- COLLSCAN je blbě
- IXSCAN je ok
- Pokud nad IXSCAN není FETCH, byl to covered index, což je fajn
- AND_SORTED, AND_HASH - použit průnik indexů
- OR - obvykle problém, nejspíš nutné spojování výsledků a řazení
- SORT - lépe se ho zbavit, nebo alespoň donutit použít index
- je dobré tedy dosáhnout scanAndOrder: false
Profiling (dlouho běžící dotazy)
Komentář k dotazu¶
- Užitečné - u findu lze ke kurzoru přihodit vlastní komentář, který se potom ukazuje v explainech, profilingu, atd.
- https://docs.mongodb.com/manual/reference/operator/meta/comment/#metaOp._S_comment
- https://docs.mongodb.com/manual/reference/method/cursor.comment/#cursor.comment
- db.col.find(query).comment("Statistics by detector")
Beletrie¶
- Optimizing MongoDB Compound Indexes - https://emptysqua.re/blog/optimizing-mongodb-compound-indexes/
- Efficient Indexing in MongoDB 2.6 - http://blog.mongodb.org/post/87790974798/efficient-indexing-in-mongodb-26
- MongoDB Indexes - http://www.toadworld.com/platforms/nosql/w/wiki/346.mongodb-indexes
- MongoDB Indexing FAQ - https://www.toadworld.com/platforms/nosql/w/wiki/347.mongodb-indexing-faq
- MongoDB Index Performance: With Compound Index - http://blog.qburst.com/2015/08/mongodb-index-performance-with-compound-index/
- Indexing Strategies - https://docs.mongodb.com/manual/applications/indexes/
- Create Indexes to Support Your Queries - https://docs.mongodb.com/manual/tutorial/create-indexes-to-support-queries/