MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Справяне с бавни заявки в MongoDB

Когато е в производство, приложението трябва да предоставя навременен отговор на потребителя с цел подобряване на взаимодействието на потребителя с приложението ви. Понякога обаче заявките към базата данни могат да започнат да забавят, поради което отнемат по-дълга латентност, за да достигне отговорът до потребителя или по-скоро операцията за пропускателна способност е прекратена поради превишаване на зададеното средно изчакване.

В този блог ще научим как можете да идентифицирате тези проблеми в MongoDB, начини да ги отстраните, когато възникнат, и какви са възможните стратегии, които да предприемете, за да не се случи това отново.

По-често това, което води до бавни отговори на заявката, е  влошен капацитет на процесора, който не е в състояние да издържи на основния работен набор. Работният набор в този случай е количеството данни и индекси, които ще бъдат подложени на екземпляр на пропускателна способност, следователно активен в този момент. Това е особено взето предвид при планирането на капацитета, когато се очаква обемът на използваните данни да се увеличава с течение на времето и броят на потребителите, ангажирани с вашата платформа.

Идентифициране на проблем с бавна заявка

Има два начина, по които можете да идентифицирате бавни заявки в MongoDB.

  1. Използване на Profiler
  2. Използване на db.currentOp() помощник

Използване на MongoDB Profiler

Профилизаторът на база данни в MongoDB е механизъм за събиране на подробна информация за командите на базата данни, изпълнявани срещу работещ екземпляр на mongod, който е:операции с пропускателна способност (Създаване, четене, актуализиране и изтриване) и команди за конфигуриране и администриране.

Профилизаторът използва ограничена колекция с име system.profile, където записва всички данни. Това означава, че когато колекцията е пълна по отношение на размера, по-старите документи се изтриват, за да се даде място за нови данни.

Профилизаторът е изключен по подразбиране, но в зависимост от нивото на профилиране можете да го активирате за база данни или за екземпляр. Възможните нива на профилиране са:

  • 0 - инструментът за профилиране е изключен, следователно не събира никакви данни.
  • 1 - инструментът за профилиране събира данни за операции, които отнемат повече време от стойността на slowms
  • 2 – инструментът за профилиране събира данни за всички операции.

 Въпреки това, активирането на профилиране генерира въздействие върху производителността върху използването на базата данни и диска, особено когато нивото на профилиране е зададено на 2. Човек трябва да обмисли всякакви последици за производителността, преди да активирате и конфигурирате профайлъра при производствено внедряване.

За да зададем профилирането, използваме помощника db.setProfilingLevel() като:

db.setProfilingLevel(2)

Примерен документ, който ще бъде съхранен в колекцията system.profile, ще бъде:

{ "was" : 0, "slowms" : 100, "sampleRate" : 1.0, "ok" : 1 }

Двойката ключ-стойност „ok“:1 показва, че операцията е успешна, докато slowms е праговото време в милисекунди, което операцията трябва да отнеме, и по подразбиране е 100 мс.

За да промените тази стойност

db.setProfilingLevel(1, { slowms: 50 })

За да потърсите данни за събирането на system.profile, изпълнете:

db.system.profile.find().pretty()

Използване на db.currentOp()helper

Тази функция изброява текущите изпълнявани заявки с много подробна информация, като например колко време се изпълняват. На работещ mongo shell изпълнявате коментара например:

db.currentOp({“secs_running”:{$gte:5}}) 

Където secs_running е стратегията за филтриране, така че да се връщат само операции, чието изпълнение е отнело повече от 5 секунди, което намалява изхода. Това често се използва, когато здравето на процесора може да бъде оценено на 100% поради неблагоприятно въздействие върху производителността, което може да повлияе  на базата данни. Така че като промените стойностите, ще научите кои заявки се изпълняват дълго.

Върнатите документи имат следните ключове, представляващи интерес:

  • заявка :какво включва заявката
  • активен : ако заявката все още е в ход.
  • ns :име на колекция, спрямо която заявката трябва да се изпълни
  • secs_running :  продължителност на заявката до момента в секунди

Като подчертавате кои заявки отнемат много време, вие идентифицирате какво претоварва процесора.

Интерпретиране на резултатите и отстраняване на проблеми

 Както описахме по-горе, забавянето на заявката е много зависимо от количеството на включени данни, което в противен случай ще доведе до неефективни планове за изпълнение. Това означава, че например, ако не използвате индекси в колекцията си и искате да актуализирате определени записи, операцията трябва да премине през всички документи, вместо да филтрира само тези, които съответстват на спецификацията на заявката. Логично, това ще отнеме повече време, което води до бавна заявка. Можете да проверите неефективен план за изпълнение, като изпълните:  objasni(‘executionStats’), което предоставя статистически данни за ефективността на заявката. От този момент можете да научите как заявката използва индекса, освен че предоставя улика дали индексът е оптимален.

Ако помощникът за обяснение се върне

{

   "queryPlanner" : {

         "plannerVersion" : 1,

         ...

         "winningPlan" : {

            "stage" : "COLLSCAN",

            ...

         }

   },

   "executionStats" : {

      "executionSuccess" : true,

      "nReturned" : 3,

      "executionTimeMillis" : 0,

      "totalKeysExamined" : 0,

      "totalDocsExamined" : 10,

      "executionStages" : {

         "stage" : "COLLSCAN",

         ...

      },

      ...

   },

   ...

}

queryPlanner.winningPlan.stage:Ключовата стойност COLLSCAN показва, че mongod е трябвало да сканира целия документ за събиране, за да идентифицира резултатите, следователно това става скъпа операция, което води до бавни заявки.

executionStats.totalKeysExamined:0 означава, че колекцията не използва стратегия за индексиране

За дадена заявка броят на участващите документи трябва да е близо до нула. Ако броят на документите е доста голям, има две възможности:

  1. Не се използва индексиране с колекцията
  2. Използване на индекс, който не е оптимален.

За да създадете индекс за колекция, изпълнете командата: 

db.collection.createIndex( { quantity: 1 } )

Където количеството е примерно поле, което сте избрали да бъде оптимално за стратегията за индексиране.

Ако искате да научите повече за индексирането и коя стратегия за индексиране да използвате, проверете в този блог

Заключение

Влошаването на производителността на базата данни може лесно да се изобрази чрез бавни заявки, което е най-малкото очакване, което бихме искали да срещнат потребителите на платформата. Човек може да идентифицира бавни заявки в MongoDB, като активира профайлъра и го конфигурира според някои спецификации или изпълни db.currentOp() на работещ екземпляр на mongod.

Като разгледаме параметрите за времето на върнатия резултат, можем да идентифицираме кои заявки изостават. След като идентифицираме тези заявки, ние използваме помощника за обясняване на тези заявки, за да получим повече подробности, например дали заявката използва някакъв индекс.

Без индексиране операциите стават скъпи, тъй като много документи трябва да бъдат сканирани, преди да се приложат промените. С този спад, процесорът ще бъде претоварен, което ще доведе до бавни заявки и нарастващи скокове на процесора.

Основната грешка, която води до бавни заявки, е неефективното планиране на изпълнение, което може лесно да бъде разрешено чрез използване на индекс с включената колекция.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB извлича стойности от BasicDBObject (Java)

  2. Създаване на администраторска зона за пет минути с AdminBro, express, mongoDB, mongoose

  3. objasni() в Mongodb:разлики между nscanned и nscannedObjects

  4. MongoDB Java Inserting Throws org.bson.codecs.configuration.CodecConfigurationException:Не мога да намеря кодек за клас io.github.ilkgunel.mongodb.Pojo

  5. Кой API на Python трябва да се използва с Mongo DB и Django