Maison > base de données > MongoDB > Parlons des types d'index riches dans MongoDB

Parlons des types d'index riches dans MongoDB

青灯夜游
Libérer: 2022-02-17 10:59:16
avant
2790 Les gens l'ont consulté

Cet article vous amènera à comprendre MongoDB et à présenter les types d'index riches dans MongoDB. J'espère qu'il sera utile à tout le monde !

Parlons des types d'index riches dans MongoDB

Les index de MongoDB et les index de MySql ont des fonctions et des principes fondamentalement similaires à suivre pour l'optimisation. code> peut être essentiellement distingué pour :MongoDB的索引和MySql的索引的作用和优化要遵循的原则基本相似,MySql索引类型基本可以区分为:

  • 单键索引 - 联合索引
  • 主键索引(聚簇索引) - 非主键索引(非聚簇索引)

MongoDB中除了这些基础的分类之外,还有一些特殊的索引类型,如: 数组索引 | 稀疏索引 | 地理空间索引 | TTL索引等.

为了下面方便测试我们使用脚本插入以下数据

for(var i = 0;i < 100000;i++){
    db.users.insertOne({
        username: "user"+i,
        age: Math.random() * 100,
        sex: i % 2,
        phone: 18468150001+i
    });
}
Copier après la connexion

单键索引

单键索引即索引的字段只有一个,是最基础的索引方式.

在集合中使用username字段,创建一个单键索引,MongoDB会自动将这个索引命名为username_1

db.users.createIndex({username:1})
&#39;username_1&#39;
Copier après la connexion

在创建索引后查看一下使用username字段的查询计划,stageIXSCAN代表使用使用了索引扫描

db.users.find({username:"user40001"}).explain()
{ 
   queryPlanner: 
   { 
     winningPlan: 
     { 
        ......
        stage: &#39;FETCH&#39;,
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { username: 1 },
           indexName: &#39;username_1&#39;,
           ......
        } 
     }
     rejectedPlans: [] ,
   },
   ......
   ok: 1 
}
Copier après la connexion

在索引优化的原则当中,有很重要的原则就是索引要建立在基数高的的字段上,所谓基数就是一个字段上不重复数值的个数,即我们在创建users集合时年龄出现的数值是0-99那么age这个字段将会有100个不重复的数值,即age字段的基数为100,而sex这个字段只会出现0 | 1这个两个值,即sex字段的基础是2,这是一个相当低的基数,在这种情况下,索引的效率并不高并且会导致索引失效.

下面就船舰一个sex字段索引,来查询执行计划会发现,查询时是走的全表扫描,而没有走相关索引.

db.users.createIndex({sex:1})
&#39;sex_1&#39;

db.users.find({sex:1}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;COLLSCAN&#39;,
        filter: { sex: { &#39;$eq&#39;: 1 } },
        direction: &#39;forward&#39; 
     },
     rejectedPlans: [] 
  },
  ......
  ok: 1 
}
Copier après la connexion

联合索引

联合索引即索引上会有多个字段,下面使用agesex两个字段创建一个索引

db.users.createIndex({age:1,sex:1})
&#39;age_1_sex_1&#39;
Copier après la connexion

然后我们使用这两个字段进行一次查询,查看执行计划,顺利地走了这条索引

db.users.find({age:23,sex:1}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { age: 1, sex: 1 },
           indexName: &#39;age_1_sex_1&#39;,
           .......
           indexBounds: { age: [ &#39;[23, 23]&#39; ], sex: [ &#39;[1, 1]&#39; ] } 
        } 
     },
     rejectedPlans: [], 
  },
  ......
  ok: 1 
 }
Copier après la connexion

数组索引

数组索引就是对数组字段创建索引,也叫做多值索引,下面为了测试将users集合中的数据增加一部分数组字段.

db.users.updateOne({username:"user1"},{$set:{hobby:["唱歌","篮球","rap"]}})
......
Copier après la connexion

创建数组索引并进行查看其执行计划,注意isMultiKey: true表示使用的索引是多值索引.

db.users.createIndex({hobby:1})
&#39;hobby_1&#39;

db.users.find({hobby:{$elemMatch:{$eq:"钓鱼"}}}).explain()
{ 
   queryPlanner: 
   { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        filter: { hobby: { &#39;$elemMatch&#39;: { &#39;$eq&#39;: &#39;钓鱼&#39; } } },
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { hobby: 1 },
           indexName: &#39;hobby_1&#39;,
           isMultiKey: true,
           multiKeyPaths: { hobby: [ &#39;hobby&#39; ] },
           ......
           indexBounds: { hobby: [ &#39;["钓鱼", "钓鱼"]&#39; ] } } 
         },
     rejectedPlans: [] 
  },
  ......
  ok: 1 
}
Copier après la connexion

数组索引相比于其它索引来说索引条目和体积必然呈倍数增加,例如平均每个文档的hobby数组的size为10,那么这个集合的hobby数组索引的条目数量将是普通索引的10倍.

联合数组索引

联合数组索引就是含有数组字段的联合索引,这种索引不支持一个索引中含有多个数组字段,即一个索引中最多能有一个数组字段,这是为了避免索引条目爆炸式增长,假设一个索引中有两个数组字段,那么这个索引条目的数量将是普通索引的n*m倍

地理空间索引

在原先的users集合上,增加一些地理信息

for(var i = 0;i < 100000;i++){
    db.users.updateOne(
    {username:"user"+i},
    {
        $set:{
            location:{
                type: "Point",
                coordinates: [100+Math.random() * 4,40+Math.random() * 3]
            }
        }
    });
}
Copier après la connexion

创建一个二维空间索引

db.users.createIndex({location:"2dsphere"})
&#39;location_2dsphere&#39;

//查询500米内的人
db.users.find({
  location:{
    $near:{
      $geometry:{type:"Point",coordinates:[102,41.5]},
      $maxDistance:500
    }
  }
})
Copier après la connexion

地理空间索引的type有很多包含Ponit(点) | LineString(线) | Polygon(多边形)

TTL索引

TTL的全拼是time to live,主要是用于过期数据自动删除,使用这种索引需要在文档中声明一个时间类型的字段,然后为这个字段创建TTL索引的时候还需要设置一个expireAfterSeconds过期时间单位为秒,创建完成后MongoDB

  • Index à clé unique - index conjoint
  • Index à clé primaire (index clusterisé) - index à clé non primaire (index non clusterisé)

in< En plus de ces classifications de base dans code>MongoDB, il existe également des types d'index spéciaux, tels que : index de tableau | index géospatial | 🎜Pour faciliter les tests ci-dessous, nous utilisons l'insertion de script. Les données suivantes🎜
for(var i = 90000;i < 100000;i++){
    db.users.updateOne(
    {username:"user"+i},
    {
        $set:{
            createdDate:new Date()
        }
    });
}
Copier après la connexion
Copier après la connexion

Index à clé unique

🎜Index à clé unique signifie qu'il n'est qu'un seul champ indexé, qui est la méthode d'indexation la plus basique.🎜🎜 Utilisez le champ username dans la collection pour créer un index à clé unique MongoDB le nommera automatiquement. index username_1🎜
db.users.createIndex({createdDate:1},{expireAfterSeconds:60})
&#39;createdDate_1&#39;
Copier après la connexion
Copier après la connexion
🎜Après la création de l'index Vérifiez le plan de requête en utilisant le champ username stage est IXSCAN. , ce qui signifie que l'analyse d'index est utilisée🎜
db.runCommand({
  collMod:"users",
  index:{
    keyPattern:{createdDate:1},
    expireAfterSeconds:120
  }
})

{ expireAfterSeconds_old: 60, expireAfterSeconds_new: 120, ok: 1 }
Copier après la connexion
Copier après la connexion
🎜 Parmi les principes d'optimisation de l'index, il y a Un principe très important est que l'index doit être construit sur un champ avec une cardinalité élevée. La soi-disant cardinalité est le nombre de non-dupliqués. valeurs ​​​​dans un champ. Autrement dit, lorsque nous créons la collection users, la valeur de age qui apparaît est 0-99Puis la age< Le champ /code> aura 100 valeurs uniques, c'est-à-dire que la base du champ <code>age est 100, et sexe< /code>Ce champ n'aura que les deux valeurs <code >0 | 1, c'est-à-dire que la base du champ sexe est 2, ce qui est une base assez faible. Dans ce cas, l'efficacité de l'index n'est pas élevée et conduira à un index. échec. 🎜🎜 Créons un index de champ sex et interrogeons le plan d'exécution. Vous constaterez que la requête utilise une analyse complète de la table au lieu de ne pas utiliser l'indexation associée.🎜
db.users.createIndex({username:1},{partialFilterExpression:{
    age:{$gt:50}
  }})
&#39;username_1&#39;

db.users.find({$and:[{username:"user4"},{age:60}]}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        filter: { age: { &#39;$eq&#39;: 60 } },
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { username: 1 },
           indexName: &#39;username_1&#39;,
           ......
           isPartial: true,
           ......
         } 
     },
     rejectedPlans: [] 
  },
  ......
  ok: 1 
}
Copier après la connexion
Copier après la connexion

Index commun

🎜L'index commun signifie qu'il y aura plusieurs champs sur l'index. Utilisez age< ci-dessous. Créez un index avec les deux champs /code> et <code>sexe 🎜
for(var i = 5000;i < 10000;i++){
  if(i < 9000){
    db.users.updateOne(
      {username:"user"+i},
      { $set:{email:(120000000+i)+"@qq.email"}}
    )
  }else{
    db.users.updateOne(
      {username:"user"+i},
      { $set:{email:null}}
    )
  }
}
Copier après la connexion
Copier après la connexion
🎜 Ensuite, nous utilisons ces deux champs pour effectuer une requête, vérifier le plan d'exécution et parcourir avec succès cet index 🎜
db.users.find({email:null})
{ 
  _id: ObjectId("61bdc01ba59136670f6536fd"),
  username: &#39;user0&#39;,
  age: 64.41483801726282,
  sex: 0,
  phone: 18468150001,
  location: 
  { 
    type: &#39;Point&#39;,
    coordinates: [ 101.42490900320335, 42.2576650823515 ] 
  } 
}
......
Copier après la connexion
Copier après la connexion

Index de tableau

🎜L'index de tableau consiste à créer un index sur le champ du tableau, également appelé index à valeurs multiples. À des fins de test, ajoutez la collection users ci-dessous. certains champs du tableau aux données. 🎜
db.users.createIndex({email:1},{sparse:true});
&#39;email_1&#39;

db.users.find({email:null}).hint({email:1})
{ 
  _id: ObjectId("61bdc12ca59136670f655a25"),
  username: &#39;user9000&#39;,
  age: 94.18397576757012,
  sex: 0,
  phone: 18468159001,
  hobby: [ &#39;钓鱼&#39;, &#39;乒乓球&#39; ],
  location: 
  { 
    type: &#39;Point&#39;,
    coordinates: [ 101.25903151863596, 41.38450145025062 ] 
  },
  email: null 
}
......
Copier après la connexion
Copier après la connexion
🎜Créez un index de tableau et affichez son plan d'exécution. Notez que isMultiKey: true signifie que l'index utilisé est un index à valeurs multiples 🎜
db.blog.insertMany([
  {title:"hello world",content:"mongodb is the best database"},
  {title:"index",content:"efficient data structure"}
])

//创建索引
db.blog.createIndex({title:"text",content:"text"})
&#39;title_text_content_text&#39;
//使用文本索引查询
db.blog.find({$text:{$search:"hello data"}})
{ 
  _id: ObjectId("61c092268c4037d17827d977"),
  title: &#39;index&#39;,
  content: &#39;efficient data structure&#39; 
},
{ 
  _id: ObjectId("61c092268c4037d17827d976"),
  title: &#39;hello world&#39;,
  content: &#39;mongodb is the best database&#39; 
}
Copier après la connexion
Copier après la connexion
🎜 L'index de tableau est. par rapport aux autres index De manière générale, les entrées et le volume de l'index doivent augmenter de façon exponentielle. Par exemple, la taille moyenne du tableau hobby de chaque document est de 10, puis le hobby. de cette collection Le nombre d'entrées dans l'index du tableau sera 10 fois supérieur à celui de l'index ordinaire 🎜🎜Index du tableau commun🎜🎜                                                                 .                                                                                                L'index de tableau commun est un index commun contenant des champs de tableau . Ce type d'index ne prend pas en charge plusieurs tableaux dans un champ d'index, c'est-à-dire qu'il ne peut y avoir qu'un seul champ de tableau dans un index. Ceci afin d'éviter la croissance explosive des entrées d'index. , alors le nombre d'entrées d'index sera de n*m ​​​​fois celui d'un index normal🎜< h3 data-id="heading-3">Index géospatial🎜Ajoutez quelques éléments géographiques informations à la collection originale des utilisateurs🎜
//对title字段创建唯一索引
db.blog.createIndex({title:1},{unique:true})
&#39;title_1&#39;
//插入一个已经存在的title值
db.blog.insertOne({title:"hello world",content:"mongodb is the best database"})
MongoServerError: E11000 duplicate key error collection: mock.blog index: title_1 dup key: { : "hello world" }
//查看一下执行计划,isUnique为true
db.blog.find({"title":"index"}).explain()
{ 
  queryPlanner: 
  { 
     ......
     winningPlan: 
     { 
        stage: &#39;FETCH&#39;,
        inputStage: 
        { 
           stage: &#39;IXSCAN&#39;,
           keyPattern: { title: 1 },
           indexName: &#39;title_1&#39;,
           isMultiKey: false,
           multiKeyPaths: { title: [] },
           isUnique: true,
           ......
         } 
     },
     rejectedPlans: [] 
  },
  .......
  ok: 1 
}
Copier après la connexion
Copier après la connexion
🎜Créer un deuxième index spatial dimensionnel🎜rrreee🎜Le type de l'index géospatial contient de nombreux Ponit(point)</code > | <code>LineString(line) | Polygone( Polygone) etc.🎜

Indice TTL< /h3>🎜 L'orthographe complète de TTL est time to live, principalement utilisée pour la suppression automatique des données expirées. Pour utiliser cet index, vous devez déclarer un champ de type heure dans le document, puis quand. En créant un index TTL pour ce champ, vous devez également définir une unité de temps d'expiration expireAfterSeconds en secondes, une fois la création terminée, MongoDB vérifiera régulièrement les données dans le fichier. collecte. Quand : 🎜
Heure actuelleTTLChamp d'index heure>ex p ire T Heure du champ d'index TL> expireAfterSrconds quand avant entre TT

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal