Maison  >  Article  >  développement back-end  >  Comment utiliser les index MongoDB

Comment utiliser les index MongoDB

小云云
小云云original
2017-12-01 11:38:252644parcourir

Dans cet article, nous partagerons avec vous une explication détaillée de l'utilisation des index MongoDB. L'index est comme la table des matières d'un livre si vous recherchez un certain contenu sans l'aide de la table des matières. vous ne pouvez rechercher et parcourir que l'intégralité de l'article, ce qui entraîne une très faible efficacité ; si vous utilisez Dans le cas d'un annuaire, vous pouvez localiser rapidement la zone où se trouve le contenu spécifique, et l'efficacité augmentera linéairement.

Introduction à l'indexation

Ouvrez d'abord la ligne de commande et entrez mongo. Par défaut, mongodb se connectera à la base de données nommée test.

➜ ~ mongo

MongoDB shell version: 2.4.9
connecting to: test
> show collections
>

Vous pouvez utiliser show collections/tables pour vérifier que la base de données est vide.

Ensuite, exécutez le code suivant dans le terminal de ligne de commande mongodb

> for(var i=0;i<100000;i++) {
... db.users.insert({username:&#39;user&#39;+i})
... }
> show collections
system.indexes
users
>

Vérifiez ensuite la base de données et constatez qu'il y a plus de system.indexes et Il existe deux tables pour les utilisateurs, la première est ce qu'on appelle l'index et la seconde est une table de base de données nouvellement créée.
De cette façon, il y a 100 000 données dans la table utilisateur.

> db.users.find()
{ "_id" : ObjectId("5694d5da8fad9e319c5b43e4"), "username" : "user0" }
{ "_id" : ObjectId("5694d5da8fad9e319c5b43e5"), "username" : "user1" }
{ "_id" : ObjectId("5694d5da8fad9e319c5b43e6"), "username" : "user2" }
{ "_id" : ObjectId("5694d5da8fad9e319c5b43e7"), "username" : "user3" }
{ "_id" : ObjectId("5694d5da8fad9e319c5b43e8"), "username" : "user4" }
{ "_id" : ObjectId("5694d5da8fad9e319c5b43e9"), "username" : "user5" }

Vous devez maintenant trouver n'importe quelle donnée. Par exemple,

> db.users.find({username: &#39;user1234&#39;})
{ "_id" : ObjectId("5694d5db8fad9e319c5b48b6"), "username" : "user1234" }

a constaté que ces données ont été trouvées avec succès, mais vous devez connaître les détails et vous devez le faire. ajoutez la méthode d'explication

   
> db.users.find({username: &#39;user1234&#39;}).explain()
{
  "cursor" : "BasicCursor",
  "isMultiKey" : false,
  "n" : 1,
  "nscannedObjects" : 100000,
  "nscanned" : 100000,
  "nscannedObjectsAllPlans" : 100000,
  "nscannedAllPlans" : 100000,
  "scanAndOrder" : false,
  "indexOnly" : false,
  "nYields" : 0,
  "nChunkSkips" : 0,
  "millis" : 30,
  "indexBounds" : {
      
  },
  "server" : "root:27017"
}

Il existe de nombreux paramètres, actuellement nous nous concentrons uniquement sur "nscanned" : 100000 et "millis" : 30.

nscanned indique le nombre total de documents numérisés par mongodb lors de la réalisation de cette requête. On constate que chaque document de la collection est numérisé et que la durée totale est de 30 millisecondes.

S'il y a 10 millions de données, elles seront parcourues à chaque fois que le document est interrogé. Eh bien, le temps est également assez considérable.

Pour de telles requêtes, l'indexation est une très bonne solution.

> db.users.ensureIndex({"username": 1})

Ensuite, recherchez user1234

> db.users.ensureIndex({"username": 1})
> db.users.find({username: 'user1234'}).explain()
{
  "cursor" : "BtreeCursor username_1",
  "isMultiKey" : false,
  "n" : 1,
  "nscannedObjects" : 1,
  "nscanned" : 1,
  "nscannedObjectsAllPlans" : 1,
  "nscannedAllPlans" : 1,
  "scanAndOrder" : false,
  "indexOnly" : false,
  "nYields" : 0,
  "nChunkSkips" : 0,
  "millis" : 0,
  "indexBounds" : {
    "username" : [
      [
        "user1234",
        "user1234"
      ]
    ]
  },
  "server" : "root:27017"
}


C'est en effet un peu incroyable. La requête est complétée en un instant, car une seule pièce. de données se trouvent via l'index, et non 100 000.

Bien sûr, l'utilisation d'index a un coût : pour chaque index ajouté, chaque opération d'écriture (insertion, mise à jour, suppression) prendra plus de temps. En effet, lorsque les données changent, non seulement le document doit être mis à jour, mais tous les index de la collection de niveaux sont également mis à jour. Par conséquent, mongodb limite chaque collection à un maximum de 64 index. En règle générale, vous ne devriez pas avoir plus de deux index sur une collection particulière.

Conseils

S'il s'agit d'une requête très générale, ou si cette requête provoque un goulot d'étranglement dans les performances, alors c'est un très bon choix pour créer un index sur un certain champ (comme nom d'utilisateur). Mais ce champ ne doit pas être indexé uniquement pour les requêtes utilisées par les administrateurs (qui ne se soucient pas du temps nécessaire à l'interrogation).

Index composite

Les valeurs de l'index sont classées dans un certain ordre, le tri des documents à l'aide de la clé d'index est donc très rapide.

db.users.find().sort({'age': 1, 'username': 1})


Ici, nous trions en fonction de age first Ensuite, triez en fonction du nom d'utilisateur, donc le nom d'utilisateur ne joue pas un grand rôle ici. Afin d'optimiser ce tri, il peut être nécessaire de créer des index sur l'âge et le nom d'utilisateur.

db.users.ensureIndex({'age':1, 'username': 1})
Cela crée un index composite (un index construit sur plusieurs champs), ce qui est très utile si les conditions de requête incluent plusieurs clés.

Une fois qu'un index composite est établi, chaque entrée d'index comprend un champ d'âge et un champ de nom d'utilisateur, et pointe vers l'emplacement de stockage du document sur le disque.
À l'heure actuelle, le champ d'âge est classé par ordre croissant strict. Si les âges sont égaux, ils seront classés par ordre croissant par nom d'utilisateur.

Méthode de requête

La requête ponctuelle

est utilisée pour interroger une seule valeur (bien qu'il puisse y avoir plusieurs documents contenant cette valeur)

db .users. find({'age': 21}).sort({'username': -1})


Parce que nous avons déjà établi un indice composite, un âge Pour un le nom d'utilisateur, l'ordre croissant (c'est-à-dire le numéro 1) est utilisé lors de l'établissement de l'index. Lorsque vous utilisez une requête ponctuelle pour trouver {age : 21}, en supposant qu'il y a encore 100 000 éléments de données, il peut y avoir de nombreuses personnes âgées de 21 ans, donc plus. plus d'une donnée sera trouvée. Puis trier({'nom d'utilisateur' : -1}) triera ces données dans l'ordre inverse, ce qui est l'intention initiale. Mais n'oublions pas « nom d'utilisateur » lors de la création d'un index : 1 est dans l'ordre croissant (du petit au grand). Si vous souhaitez obtenir l'ordre inverse, commencez simplement par le dernier index des données et parcourez afin d'obtenir celui souhaité. résultat.

Le sens de tri n'est pas important, mongodb peut parcourir l'index dans n'importe quelle direction.
Pour résumer, l'index composite est très efficace en requête ponctuelle. Il localise directement l'âge et n'a pas besoin de trier les résultats et de renvoyer les résultats.

Requête multi-valeurs (requête multi-valeurs)

db.users.find({'age': {"$gte": 21, "$lte": 30}} )


Trouver des documents qui correspondent à plusieurs valeurs. Les requêtes à valeurs multiples peuvent également être comprises comme des requêtes à points multiples.
Comme ci-dessus, l'âge à trouver se situe entre 21 et 30 ans. monogdb utilisera la première clé "age" de l'index pour obtenir des résultats correspondants, et les résultats sont généralement classés par ordre d'index.

db.users.find({'age': {"$gte": 21, "$lte": 30}}).sort({'username': 1})


与上一个类似,这次需要对结果排序。
在没有sort时,我们查询的结果首先是根据age等于21,age等于22..这样从小到大排序,当age等于21有多个时,在进行usernameA-Z(0-9)这样排序。所以,sort({'username': 1}),要将所有结果通过名字升序排列,这次不得不先在内存中进行排序,然后返回。效率不如上一个高。

当然,在文档非常少的情况,排序也花费不了多少时间。
如果结果集很大,比如超过32MB,MongoDB会拒绝对如此多的数据进行排序工作。

还有另外一种解决方案

也可以建立另外一个索引{'username': 1, 'age': 1}, 如果先对username建立索引,当再sortusername,相当没有进行排序。但是需要在整个文档查找age等于21的帅哥美女,所以搜寻时间就长了。

但哪个效率更高呢?

如果建立多个索引,如何选择使用哪个呢?
效率高低是分情况的,如果在没有限制的情况下,不用进行排序但需要搜索整个集合时间会远超过前者。但是在返回部分数据(比如limit(1000)),新的赢家就产生了。

   
>db.users.find({&#39;age&#39;: {"$gte": 21, "$lte": 30}}).
sort({username&#39;: 1}).
limit(1000).
hint({&#39;age&#39;: 1, &#39;username&#39;: 1})
explain()[&#39;millis&#39;]
2031ms
  
>db.users.find({&#39;age&#39;: {"$gte": 21, "$lte": 30}}).
sort({username&#39;: 1}).
limit(1000).
hint({&#39;username&#39;: 1, &#39;age&#39;: 1}).
explain()[&#39;millis&#39;]
181ms


其中可以使用hint指定要使用的索引。
所以这种方式还是很有优势的。比如一般场景下,我们不会把所有的数据都取出来,只是去查询最近的,所以这种效率也会更高。

索引类型

唯一索引

可以确保集合的每个文档的指定键都有唯一值。

db.users.ensureIndex({&#39;username&#39;: 1, unique: 
true})


比如使用mongoose框架,在定义schema时,即可指定unique: true.
如果插入2个相同都叫张三的数据,第二次插入的则会失败。_id即为唯一索引,并且不能删除。

稀疏索引

使用sparse可以创建稀疏索引

>db.users.ensureIndex({&#39;email&#39;: 1}, {&#39;unique&#39;: true, &#39;sparse&#39;: 
true})

索引管理

system.indexes集合中包含了每个索引的详细信息

db.system.indexes.find()

1.ensureIndex()创建索引

db.users.ensureIndex({&#39;username&#39;: 
1})


后台创建索引,这样数据库再创建索引的同时,仍然能够处理读写请求,可以指定background选项。

db.test.ensureIndex({"username":1},{"background":true})

2.getIndexes()查看索引

db.collectionName.getIndexes()
db.users.getIndexes()
[
  {
    "v" : 1,
    "key" : {
      "_id" : 1
    },
    "ns" : "test.users",
    "name" : "_id_"
  },
  {
    "v" : 1,
    "key" : {
      "username" : 1
    },
    "ns" : "test.users",
    "name" : "username_1"
  }
]


其中v字段只在内部使用,用于标识索引版本。

3.dropIndex删除索引

> db.users.dropIndex("username_1")
{ "nIndexesWas" : 2, "ok" : 1 }


全选复制放进笔记> db.users.dropIndex({"username":1})

以上内容就是MongoDB索引的使用详解,希望对大家有帮助。

相关推荐:

MongoDB的技巧与注意事项汇总

MongoDB索引概念及使用详解

Dex – MongoDB索引优化工具

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
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