sql >> Databáze >  >> NoSQL >> MongoDB

Výkon dotazování MongoDB pro více než 5 milionů záznamů

Tohle je hledání jehly v kupce sena. Potřebovali bychom nějaký výstup explain() pro ty dotazy, které nefungují dobře. Bohužel i to by problém vyřešilo pouze pro tento konkrétní dotaz, takže zde je strategie, jak k tomu přistupovat:

  1. Ujistěte se, že to není kvůli nedostatečné paměti RAM a nadměrnému stránkování
  2. Povolte DB profiler (pomocí db.setProfilingLevel(1, timeout) kde timeout je prahová hodnota pro počet milisekund, které dotaz nebo příkaz zabere, cokoliv pomalejšího bude zaznamenáno)
  3. Prohlédněte si pomalé dotazy v db.system.profile a spusťte dotazy ručně pomocí explain()
  4. Zkuste identifikovat pomalé operace v explain() výstup, jako je scanAndOrder nebo velké nscanned atd.
  5. Důvod týkající se selektivity dotazu a toho, zda je možné dotaz vůbec zlepšit pomocí indexu . Pokud ne, zvažte nepovolení nastavení filtru pro koncového uživatele nebo mu dejte varovné dialogové okno, že operace může být pomalá.

Klíčovým problémem je, že zjevně umožňujete svým uživatelům libovolně kombinovat filtry. Bez protínání indexů to dramaticky zvýší počet požadovaných indexů.

Také slepé házení indexu na každý možný dotaz je velmi špatná strategie. Je důležité strukturovat dotazy a ujistit se, že indexovaná pole mají dostatečnou selektivitu .

Řekněme, že máte dotaz pro všechny uživatele se status "aktivní" a některá další kritéria. Ale z 5 milionů uživatelů jsou 3 miliony aktivních a 2 miliony ne, takže více než 5 milionů položek má pouze dvě různé hodnoty. Takový index obvykle nepomůže. Je lepší nejprve vyhledat ostatní kritéria a poté skenovat výsledky. V průměru budete muset při vrácení 100 dokumentů naskenovat 167 dokumentů, což výkonu příliš neutrpí. Ale není to tak jednoduché. Pokud je primárním kritériem joined_at datum uživatele a pravděpodobnost, že uživatelé časem přestanou používat, je vysoká, možná budete muset skenovat tisíce dokumentů před nalezením stovky shod.

Optimalizace tedy velmi závisí na datech (nejen jejich struktuře , ale také samotná data ), jeho vnitřní korelace a vaše vzorce dotazů .

Věci se zhoršují, když jsou data příliš velká pro RAM, protože pak je mít index skvělé, ale skenování (nebo dokonce prosté vracení) výsledků může vyžadovat náhodné načítání velkého množství dat z disku, což zabere spoustu času.

Nejlepší způsob, jak to kontrolovat, je omezit počet různých typů dotazů, zakázat dotazy na informace s nízkou selektivitou a pokusit se zabránit náhodnému přístupu ke starým datům.

Pokud vše ostatní selže a pokud opravdu potřebujete takovou flexibilitu ve filtrech, mohlo by být užitečné zvážit samostatnou vyhledávací databázi, která podporuje průniky indexů, načíst mongo id odtud a poté získat výsledky z mongo pomocí $in . Ale to je plné svých vlastních nebezpečí.

-- UPRAVIT --

Vysvětlení, které jste zaslali, je krásným příkladem problému se skenováním polí s nízkou selektivitou. Zdá se, že existuje mnoho dokumentů pro "[email protected]". Nyní je nalezení těchto dokumentů a jejich řazení sestupně podle časového razítka docela rychlé, protože je podporováno vysoce selektivními indexy. Bohužel, protože existují pouze dva typy zařízení, mongo potřebuje naskenovat 30060 dokumentů, aby našlo první, které odpovídá 'mobilní'.

Předpokládám, že se jedná o nějaký druh sledování webu a způsob používání uživatele zpomaluje dotaz (pokud by denně měnil mobil a web, byl by dotaz rychlý).

Zrychlení tohoto konkrétního dotazu lze provést pomocí složeného indexu, který obsahuje typ zařízení, např. pomocí

a) ensureIndex({'username': 1, 'userAgent.deviceType' : 1, 'timestamp' :-1})

nebo

b) ensureIndex({'userAgent.deviceType' : 1, 'username' : 1, 'timestamp' :-1})

Bohužel to znamená, že dotazy jako find({"username" : "foo"}).sort({"timestamp" : -1}); již nelze používat stejný index, takže, jak je popsáno, počet indexů velmi rychle poroste.

Obávám se, že v tuto chvíli pro to pomocí mongodb neexistuje žádné dobré řešení.



  1. Jaké jsou konvence pojmenování pro MongoDB?

  2. ID objektu nodejs mongodb na řetězec

  3. MongoDB:Je možné vytvořit dotaz bez ohledu na velikost písmen?

  4. MongoDB Find Exact Array Match, ale na pořadí nezáleží