Heim >Backend-Entwicklung >PHP-Tutorial >So verwenden Sie MongoDB-Indizes

So verwenden Sie MongoDB-Indizes

小云云
小云云Original
2017-12-01 11:38:252663Durchsuche

In diesem Artikel geben wir Ihnen eine detaillierte Erklärung zur Verwendung von MongoDB-Indizes. Der Index ist wie das Inhaltsverzeichnis eines Buches. Wenn Sie nach einem bestimmten Inhalt suchen, ohne die Hilfe des Inhaltsverzeichnisses. Sie können nur den gesamten Artikel durchsuchen und durchsuchen, was zu einer sehr geringen Effizienz führt. Wenn Sie ein Verzeichnis verwenden, können Sie schnell den Bereich finden, in dem sich der spezifische Inhalt befindet, und die Effizienz steigt linear.

Einführung in die Indizierung

Öffnen Sie zunächst die Befehlszeile und geben Sie mongo ein. Standardmäßig stellt mongodb eine Verbindung zur Datenbank namens test her.

➜ ~ mongo

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

Sie können Show Collections/Tables verwenden, um zu überprüfen, ob die Datenbank leer ist.

Führen Sie dann den folgenden Code im Mongodb-Befehlszeilenterminal aus

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

Überprüfen Sie dann die Datenbank und stellen Sie fest, dass weitere system.indexes und vorhanden sind Es gibt zwei Tabellen für Benutzer, die erste ist der sogenannte Index und die zweite ist eine neu erstellte Datenbanktabelle.
Auf diese Weise befinden sich 100.000 Daten in der Benutzertabelle.

> 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" }

Jetzt müssen Sie ein beliebiges Datenelement finden. Beispielsweise hat

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

festgestellt, dass diese Daten erfolgreich gefunden wurden, aber Sie müssen die Details kennen und müssen Fügen Sie die EXPLAIN-Methode hinzu

   
> 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"
}

Es gibt viele Parameter, derzeit konzentrieren wir uns nur auf „nscanned“: 100000 und „millis“: 30.

nscanned gibt die Gesamtzahl der von mongodb während des Abschlusses dieser Abfrage gescannten Dokumente an. Es kann festgestellt werden, dass jedes Dokument in der Sammlung gescannt wird und die Gesamtzeit 30 Millisekunden beträgt.

Wenn 10 Millionen Daten vorhanden sind, werden diese bei jeder Abfrage des Dokuments durchlaufen. Nun, die Zeit ist auch ziemlich beträchtlich.

Für solche Abfragen ist die Indizierung eine sehr gute Lösung.

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

Dann suchen Sie nach 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"
}


Die Abfrage ist in der Tat im Handumdrehen abgeschlossen, da nur ein Teil vorhanden ist der Daten werden über den Index gefunden, und nicht 100.000.

Natürlich ist die Verwendung von Indizes mit Kosten verbunden: Für jeden hinzugefügten Index nimmt jeder Schreibvorgang (Einfügen, Aktualisieren, Löschen) mehr Zeit in Anspruch. Denn wenn sich die Daten ändern, muss nicht nur das Dokument aktualisiert werden, sondern auch alle Indizes der Ebenensammlung werden aktualisiert. Daher begrenzt Mongodb jede Sammlung auf maximal 64 Indizes. Im Allgemeinen sollten Sie nicht mehr als zwei Indizes für eine bestimmte Sammlung haben.

Tipps

Wenn es sich um eine sehr allgemeine Abfrage handelt oder diese Abfrage einen Leistungsengpass verursacht, ist es eine sehr gute Wahl, einen Index für ein bestimmtes Feld zu erstellen (z. B Benutzername). Dieses Feld sollte jedoch nicht nur für Abfragen indiziert werden, die von Administratoren verwendet werden (denen die für die Abfrage benötigte Zeit egal ist).

Zusammengesetzter Index

Die Werte des Index sind in einer bestimmten Reihenfolge angeordnet, sodass das Sortieren von Dokumenten mithilfe des Indexschlüssels sehr schnell erfolgt.

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


Hier wird nach sortiert Alter zuerst Dann nach Benutzernamen sortieren, daher spielt der Benutzername hier keine große Rolle. Um diese Sortierung zu optimieren, kann es notwendig sein, Indizes nach Alter und Benutzername zu erstellen.

db.users.ensureIndex({'age':1, 'username': 1})
Dadurch wird ein zusammengesetzter Index erstellt (ein Index, der auf mehreren Feldern basiert), was sehr nützlich ist, wenn die Abfragebedingungen mehrere Schlüssel umfassen.

Nachdem ein zusammengesetzter Index erstellt wurde, enthält jeder Indexeintrag ein Altersfeld und ein Benutzernamenfeld und verweist auf den Speicherort des Dokuments auf der Festplatte.
Zu diesem Zeitpunkt ist das Altersfeld in streng aufsteigender Reihenfolge angeordnet. Wenn die Altersgruppen gleich sind, werden sie in aufsteigender Reihenfolge nach Benutzernamen sortiert.

Abfragemethode

Punktabfrage

wird verwendet, um einen einzelnen Wert abzufragen (obwohl mehrere Dokumente diesen Wert enthalten können)

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


Da wir bereits einen zusammengesetzten Index erstellt haben, ein Alter für a Benutzername, aufsteigende Reihenfolge (d. h. Nummer 1) wird beim Erstellen des Indexes verwendet. Wenn die Punktabfrage verwendet wird, um {Alter: 21} zu finden, gibt es unter der Annahme, dass noch 100.000 Daten vorhanden sind, möglicherweise viele Personen im Alter von 21 Jahren, also mehr Es wird mehr als ein Datenelement gefunden. Dann sort({'Benutzername': -1}) sortiert diese Daten in umgekehrter Reihenfolge, was die ursprüngliche Absicht ist. Aber vergessen wir beim Erstellen eines Indexes nicht: 1 ist in aufsteigender Reihenfolge (von klein nach groß). Wenn Sie die umgekehrte Reihenfolge erhalten möchten, beginnen Sie einfach mit dem letzten Index der Daten und durchlaufen Sie diese, um das gewünschte Ergebnis zu erhalten Ergebnis.

Die Sortierrichtung ist nicht wichtig, Mongodb kann den Index aus jeder Richtung durchlaufen.
Zusammenfassend lässt sich sagen, dass der zusammengesetzte Index bei der Punktabfrage sehr effizient ist. Er lokalisiert das Alter direkt und muss die Ergebnisse nicht sortieren und zurückgeben.

Mehrwertige Abfrage (multi-value-query)

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


Dokumente suchen, die mehreren Werten entsprechen. Mehrwertige Abfragen können auch als Mehrfachpunktabfragen verstanden werden.
Wie oben liegt das Alter zwischen 21 und 30 Jahren. monogdb verwendet den ersten Schlüssel „Alter“ im Index, um passende Ergebnisse zu erhalten, und die Ergebnisse werden normalerweise in Indexreihenfolge angeordnet.

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索引优化工具

Das obige ist der detaillierte Inhalt vonSo verwenden Sie MongoDB-Indizes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn