sql >> Database >  >> NoSQL >> MongoDB

MongoDB Regex, Index &Prestaties

MongoDB ondersteunt reguliere expressies met behulp van de $ regex-operator. Deze MongoDB-regex-query's hebben echter een keerzijde, op één na maken alle typen regex slecht gebruik van indexen en resulteren in prestatieproblemen. Voor een productieserver met grote hoeveelheden gegevens kan een slechte regex-query uw server op de knieën brengen.

Op MongoDB gebaseerde zoekopdrachten zijn een vrij veel voorkomende zoekopdracht in de meeste toepassingen die MongoDB gebruiken. Dit is vergelijkbaar met de 'LIKE'-bewerking die wordt ondersteund door de meeste relationele databases. De syntaxis van de opdracht is als volgt

{ $regex: /pattern/, $options: '<options>' }
E.g. { name: { $regex: /^acme.*test/}}

Raadpleeg de MongoDB-documentatie voor meer gedetailleerde informatie over de regex-bewerking en extra opties.

Voor de rest van deze discussie gaan we ervan uit dat het veld waarmee u vergelijkt een index heeft. Als u niet indexeert, resulteert dit in een collectiescan en zeer slechte prestaties. Zelfs als het veld is geïndexeerd, kan dit echter tot slechte prestaties leiden. De reden is dat MongoDB alleen goed gebruik kan maken van indexen als uw reguliere expressie een "prefixexpressie" is - dit zijn expressies die beginnen met het "^"-teken.

bijv. { name: { $regex: /^acme/}}

Hierdoor kan MongoDB een reeks indexitems identificeren die relevant zijn voor deze zoekopdracht en resulteren in efficiënte zoekopdrachten. Elke andere zoekopdracht resulteert in een indexscan, aangezien MongoDB de scan niet kan beperken tot een reeks indexitems. Een indexscan is bijzonder slecht omdat alle indexen in het geheugen moeten worden gepagineerd en dit heeft invloed op de werkset van uw server (in feite kan de indexscan leiden tot slechtere prestaties dan een collectiescan - het resulteert in tweemaal het aantal paginafouten ).

Laten we eens kijken naar enkele voorbeelden en de resulterende queryplannen. Voor onze testdoeleinden heb ik een verzameling opgezet met 100.000 documenten. Elk document heeft een veld voornaam, een tekenreeks van 16 tekens.

Voorbeeld 1: { name:{ $regex:/^acme/}}
Resultaat:efficiënt indexgebruik
Queryplan:

executionStats" : {
       "executionSuccess" : true,
       "nReturned" : 0,
       "executionTimeMillis" : 0,
       "totalKeysExamined" : 1,
       "totalDocsExamined" : 0,

Voorbeeld 2: { name:{ $regex:/^acme/i}}
Resultaat:Inefficiënte indexscan vanwege hoofdletterongevoelige vereiste. Dus eigenlijk negeert de /i-optie de "prefix-expressie"
Queryplan:

        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 137,
                "totalKeysExamined" : 100000,
                "totalDocsExamined" : 0,

Voorbeeld 3: { name:{ $regex:/acme.*corp/}}
Resultaat:Inefficiënte indexscan
Queryplan:

                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 167,
                "totalKeysExamined" : 100000,
                "totalDocsExamined" : 0,

Voorbeeld 4: { name:{ $regex:/acme/}}
Resultaat:Inefficiënte indexscan

        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 130,
                "totalKeysExamined" : 100000,
                "totalDocsExamined" : 0,

  1. Op afstand verbinding maken met MongoDB http-interface op EC2-server

  2. Mongodb vinden in sub-array

  3. schemakenmerken ophalen van Mongoose Model

  4. hoe krijg ik alle sleutels en waarden in redis in javascript?