Query Optimization / Identify and Resolve Slow Queries

Code Summary: Identifying and Analyzing Slow Queries in the MongoDB Shell

Enable the Database Profiler

Here’s an example of enabling the Database Profiler:

db.setProfilingLevel(1)

The value passed as the argument determines the profiling level. The Database Profiler has the following profiling levels:

0 - The profiler is off and does not collect any data. This is the default profiler level.

1 - The profiler collects data for operations that exceed the slowms threshold or match a specified filter.

2 - The profiler collects data for all operations.

Here is an example of setting the Database Profiler to capture all operations that take longer than 50 milliseconds to execute by supplying a slowms threshold.

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

Query the Database Profiler

Here is an example of how to query the Database Profiler for the top query sorted by longest operation times in milliseconds.

db.system.profile.find().sort({millis: -1}).limit(1)
[
  {
    op: 'query',
    ns: 'sample_airbnb.listingsAndReviews',
    command: {
      find: 'listingsAndReviews',
      filter: {
        'address.market': 'Rio De Janeiro',
        price: { '$lte': Decimal128('200.00') },
        bedrooms: { '$gte': 2 },
        minimum_nights: { '$lte': '2' },
        amenities: 'Wifi'
      },
      sort: { price: -1 },
      projection: {
        listing_url: 1,
        name: 1,
        property_type: 1,
        minimum_nights: 1,
        bedrooms: 1,
        amenities: 1,
        price: 1,
        'address.market': 1,
        _id: 0
      },
      apiVersion: '1',
      lsid: { id: UUID('d34b837f-ae63-499d-9ac3-103436397d0a') },
      '$clusterTime': {
        clusterTime: Timestamp({ t: 1739404444, i: 1 }),
        signature: {
          hash: Binary.createFromBase64('fjgh1wfz1zfb4YwyhURuGGCv2z4=', 0),
          keyId: Long('7430811807452758018')
        }
      },
      '$db': 'sample_airbnb'
    },
    keysExamined: 63,
    docsExamined: 14,
    fromMultiPlanner: true,
    nBatches: 1,
    cursorExhausted: true,
    numYield: 5,
    nreturned: 14,
    planCacheShapeHash: 'C39BEC33',
    planCacheKey: '24D99D4D',
    queryShapeHash: '7CC9C566FBEC7456338D861AA79FA03BBE88C53C11D2749F31EAA64ABBD38042',
    queryFramework: 'classic',
    locks: { Global: { acquireCount: { r: Long('7') } } },
    flowControl: {},
    readConcern: { level: 'local', provenance: 'implicitDefault' },
    storage: {
      data: { bytesRead: Long('4785220'), timeReadingMicros: Long('80718') }
    },
    responseLength: 10256,
    protocol: 'op_msg',
    cpuNanos: 18346272,
    millis: 106,
    planSummary: 'IXSCAN { address.market: 1, amenities: 1, price: -1, bedrooms: 1, minimum_nights: 1, listing_url: 1, name: 1, property_type: 1 }',
    planningTimeMicros: 106690,
    execStats: {
      isCached: false,
      stage: 'PROJECTION_DEFAULT',
      nReturned: 14,
      executionTimeMillisEstimate: 30,
      works: 64,
      advanced: 14,
      needTime: 48,
      needYield: 0,
      saveState: 5,
      restoreState: 5,
      isEOF: 1,
      transformBy: {},
      inputStage: {
        stage: 'FETCH',
        nReturned: 14,
        executionTimeMillisEstimate: 30,
        works: 64,
        advanced: 14,
        needTime: 48,
        needYield: 0,
        saveState: 5,
        restoreState: 5,
        isEOF: 1,
        docsExamined: 14,
        alreadyHasObj: 0,
        inputStage: {
          stage: 'IXSCAN',
          nReturned: 14,
          executionTimeMillisEstimate: 10,
          works: 63,
          advanced: 14,
          needTime: 48,
          needYield: 0,
          saveState: 5,
          restoreState: 5,
          isEOF: 1,
          keyPattern: {
            'address.market': 1,
            amenities: 1,
            price: -1,
            bedrooms: 1,
            minimum_nights: 1,
            listing_url: 1,
            name: 1,
            property_type: 1
          },
          indexName: 'address.market_1_amenities_1_price_-1_bedrooms_1_minimum_nights_1_listing_url_1_name_1_property_type_1',
          isMultiKey: true,
          multiKeyPaths: {
            'address.market': [],
            amenities: [ 'amenities' ],
            price: [],
            bedrooms: [],
            minimum_nights: [],
            listing_url: [],
            name: [],
            property_type: []
          },
          isUnique: false,
          isSparse: false,
          isPartial: false,
          indexVersion: 2,
          direction: 'forward',
          indexBounds: {
            'address.market': [ '["Rio De Janeiro", "Rio De Janeiro"]' ],
            amenities: [ '["Wifi", "Wifi"]' ],
            price: [ '[200.00, -inf.0]' ],
            bedrooms: [ '[2, inf.0]' ],
            minimum_nights: [ '["", "2"]' ],
            listing_url: [ '[MinKey, MaxKey]' ],
            name: [ '[MinKey, MaxKey]' ],
            property_type: [ '[MinKey, MaxKey]' ]
          },
          keysExamined: 63,
          seeks: 49,
          dupsTested: 14,
          dupsDropped: 0
        }
      }
    },
    ts: ISODate('2025-02-12T23:54:26.426Z'),
    client: '255.255.255.255',
    appName: 'mongosh 2.3.6',
    allUsers: [ { user: 'user', db: 'admin' } ],
    user: 'user@admin'
  }
]

Disable the Database Profiler

Here’s an example of how to disable the Database profiler

db.setProfilingLevel(0)

Search the MongoDB Log Files

You can use the grep command to search the MongoDB log files for slow operations

grep "Slow query" /path/to/logfile

This will return the log entries that were recorded for queries that exceeded the slowms threshold as seen here:

{"t":{"$date":"2025-01-08T18:06:37.637+00:00"},"s":"I",  "c":"COMMAND",  "id":51803,   "ctx":"conn7814","msg":"Slow query","attr":{"type":"command","isFromUserConnection":true,"ns":"sample_airbnb.listingsAndReviews_big_collection","collectionType":"normal","appName":"mongosh 2.3.6","queryShapeHash":"4E96296E301A995A57D8622997052D4AC355B7BA8702E4461739A9D10A65EC38","command":{"find":"listingsAndReviews_big_collection","filter":{"property_type":"House","room_type":"Entire home/apt","minimum_nights":{"$gt":2},"maximum_nights":{"$lte":30},"bedrooms":{"$gte":2}},"sort":{"number_of_reviews":-1},"apiVersion":"1","lsid":{"id":{"$uuid":"690c1cdb-5148-43bb-b551-d5ea935780e0"}},"$clusterTime":{"clusterTime":{"$timestamp":{"t":1736359504,"i":1}},"signature":{"hash":{"$binary":{"base64":"bUmxaMztfcHfJ3PKP+8Wz8lJeAQ=","subType":"0"}},"keyId":7397043374412267521}},"$db":"sample_airbnb"},"planSummary":"COLLSCAN","planningTimeMicros":203,"keysExamined":0,"docsExamined":55550,"hasSortStage":true,"nBatches":1,"cursorExhausted":true,"numYields":199,"nreturned":0,"planCacheShapeHash":"16DDFF73","planCacheKey":"E3E1C84F","queryFramework":"classic","reslen":261,"locks":{"Global":{"acquireCount":{"r":201}}},"readConcern":{"level":"local","provenance":"implicitDefault"},"storage":{"data":{"bytesRead":893739220,"timeReadingMicros":3073882},"timeWaitingMicros":{"cache":4}},"cpuNanos":949972045,"remote":"104.30.134.190:37157","protocol":"op_msg","queues":{"execution":{"admissions":200},"ingress":{"admissions":1}},"workingMillis":3746,"durationMillis":3746}}