Inhaltsverzeichnis
Vorwort
1. Was genau ist ein Index?
(1) Mehrere Implementierungsmethoden und Funktionen des Index
(2) Speicherung von Daten und Index
(3) Gedanken nach Kenntnis des Implementierungs- und Speicherprinzips des Index
2. Zusammengesetzter Index
(1) Je mehr zusammengesetzte Indizes, desto besser
三、总结:
彩蛋
Heim Datenbank SQL Best Practices für MongoDB-Indizes

Best Practices für MongoDB-Indizes

Jun 24, 2019 pm 05:36 PM
mongodb 索引

Best Practices für MongoDB-Indizes

Vorwort

Die meisten Entwickler wissen, dass die Indizierung schneller ist. Im eigentlichen Prozess stoßen wir jedoch häufig auf einige Fragen und Schwierigkeiten:

  • Die von uns abgefragten Felder haben unterschiedliche Fälle. Müssen alle an der Abfrage beteiligten Felder indiziert werden?
  • Wie wähle ich zwischen zusammengesetztem Index und einzelnem Feld? Ist es besser, beide oder jeweils ein einzelnes Feld hinzuzufügen?
  • Gibt es Nebenwirkungen beim Hinzufügen eines Index?
  • Der Index wurde hinzugefügt, aber er ist immer noch nicht schnell genug? was zu tun?

Dieser Artikel versucht, die Grundkenntnisse der Indizierung zu erläutern und die oben genannten Fragen zu beantworten.

1. Was genau ist ein Index?

Die meisten Entwickler, die mit Indizes in Berührung kommen, wissen wahrscheinlich, dass Indizes dem Katalog von Büchern ähneln. Sie müssen den gewünschten Inhalt finden, die qualifizierten Schlüsselwörter im Katalog finden und dann die Seitennummer des Buchs finden entsprechendes Kapitel und suchen Sie dann den spezifischen Inhalt.
In der Datenstruktur ähnelt die einfachste Indeximplementierung einer Hashmap, die über den Schlüsselwortschlüssel einem bestimmten Ort zugeordnet wird, um den spezifischen Inhalt zu finden. Doch zusätzlich zum Hashing gibt es viele Möglichkeiten, die Indizierung zu implementieren.

(1) Mehrere Implementierungsmethoden und Funktionen des Index

Hash / B-Tree / B+-Tree redis HSET / MongoDB&PostgreSQL / MySQL

Hashmap

Best Practices für MongoDB-Indizes

Unterschied:

Best Practices für MongoDB-Indizes

  • B+-Tree-Blätter speichern Daten, Nicht-Blätter speichern Indizes, es werden keine Daten gespeichert, es gibt Verknüpfungen zwischen Blättern
  • B-Tree-Nicht-Blätter können Daten speichern

In Bezug auf die Komplexität der Algorithmussuche:

  • Hash liegt nahe bei O(1)
  • b-Baum O(1)~ O(Log(n )) schnellere durchschnittliche Suchzeit, instabile Abfragezeit
  • b+ Tree O(Log(n)) kontinuierliche Daten, Abfragestabilität

Warum MongoDB B-Tree anstelle von B+ wählt - für seinen Implementierungsbaum?
Viele Artikel im Internet haben dies erklärt, aber es ist nicht der Schwerpunkt dieses Artikels.

(2) Speicherung von Daten und Index

Best Practices für MongoDB-IndizesDer Index sollte so weit wie möglich im Speicher gespeichert werden, die Daten an zweiter Stelle.
Achten Sie darauf, nur die notwendigen Indizes beizubehalten und den Speicher so weit wie möglich zu nutzen.
Wenn der Indexspeicher fast voll ist, kann die Festplatte leichter gelesen werden und die Geschwindigkeit verringert sich.

(3) Gedanken nach Kenntnis des Implementierungs- und Speicherprinzips des Index

Einfügen/Aktualisieren/Löschen löst den Neuausgleichsbaum aus. Wenn also Daten hinzugefügt, gelöscht oder geändert werden, wird der Index ausgelöst Bei einer Änderung kommt es zu einem Leistungsverlust. Je mehr Indizes, desto besser. Welche Felder sollten in diesem Fall als Indizes ausgewählt werden? Was soll ich tun, wenn die Abfrage diese Bedingungen verwendet?
Nehmen Sie als Beispiel die einfachste Hashmap. Warum ist die Komplexität nicht O (1), sondern sozusagen nahe an O (1). Da es Schlüsselkonflikte/Duplikate gibt, muss die Datenbank bei der Suche danach immer noch abwechselnd weitersuchen, wenn es viele Daten mit Schlüsselkonflikten gibt. Das Gleiche gilt für B-Tree, wenn man sich die Schlüsselauswahl ansieht.
Ein Fehler, den die meisten Entwickler häufig machen, besteht darin, Schlüssel zu indizieren, die keine Unterscheidung haben. Beispielsweise verfügen viele Sammlungen nur über zentralisierte Kategorien von Typ-/Statusdokumenten mit einer Anzahl von Hunderttausenden oder mehr. Normalerweise ist diese Art von Index nicht hilfreich.

2. Zusammengesetzter Index

(1) Je mehr zusammengesetzte Indizes, desto besser

Wenn Sie nicht mehr redundante Indizes erstellen möchten, werden die Entwicklungskollegen zusammengesetzte auswählen & einzelne Felder Es ist manchmal ziemlich verwirrend. Machen wir ein paar Experimente anhand typischer Begegnungsszenarien:
Hier entsteht eine Kreditsammlung. Vereinfachen Sie auf nur 100 Daten. Diese Darlehenstabelle hat _id, userId, Status (Darlehensstatus), Betrag (Betrag). Als nächstes erstellen wir jeweils mehrere Indizes.

Schritt 1: Erstellen Sie zuerst {userId:1, status:1}db.loans.count()100

db.loans.find({ "userId" : "59e022d33f239800129c61c7", "status" : "repayed", }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "$and" : [
   {
     "status" : {
       "$eq" : "repayed"
     }
   },
   {
     "userId" : {
       "$eq" : "59e022d33f239800129c61c7"
     }
   }
 ]
},
"queryHash" : "15D5A9A1",
"planCacheKey" : "15D5A9A1",
"winningPlan" : {
 "stage" : "COLLSCAN",
 "filter" : {
   "$and" : [
     {
       "status" : {
         "$eq" : "repayed"
       }
     },
     {
       "userId" : {
         "$eq" : "59e022d33f239800129c61c7"
       }
     }
   ]
 },
 "direction" : "forward"
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren
rrree

Ergebnis: {userId:1, status:1} wird als Gewinnerplan ausgewählt.
Schritt 2: Erstellen Sie eine typische Index-Benutzer-ID

db.loans.createIndex({userId:1, status:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
Nach dem Login kopieren
rrreeBeachten Sie, dass DB {userId:1, status:1} als bessere Ausführungslösung erkennt.

db.loans.find({ "userId" : "59e022d33f239800129c61c7", "status" : "repayed", }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "$and" : [
   {
     "status" : {
       "$eq" : "repayed"
     }
   },
   {
     "userId" : {
       "$eq" : "59e022d33f239800129c61c7"
     }
   }
 ]
},
"queryHash" : "15D5A9A1",
"planCacheKey" : "BB87F2BA",
"winningPlan" : {
 "stage" : "FETCH",
 "inputStage" : {
   "stage" : "IXSCAN",
   "keyPattern" : {
     "userId" : 1,
     "status" : 1
   },
   "indexName" : "userId_1_status_1",
   "isMultiKey" : false,
   "multiKeyPaths" : {
     "userId" : [ ],
     "status" : [ ]
   },
   "isUnique" : false,
   "isSparse" : false,
   "isPartial" : false,
   "indexVersion" : 2,
   "direction" : "forward",
   "indexBounds" : {
     "userId" : [
       "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
     ],
     "status" : [
       "["repayed", "repayed"]"
     ]
   }
 }
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren
Beachten Sie, dass DB {userId:1} als Lösung für eine bessere Ausführung erkennt, hmm~, wie wir erwartet haben.
db.loans.createIndex({userId:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
Nach dem Login kopieren

Interessanter Teil: Status trifft nicht auf den Index, vollständiger Tabellenscan

Der nächste Schritt besteht darin, eine Sortierung hinzuzufügen:

db.loans.find({ "userId" : "59e022d33f239800129c61c7", "status" : "repayed", }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "$and" : [
   {
     "status" : {
       "$eq" : "repayed"
     }
   },
   {
     "userId" : {
       "$eq" : "59e022d33f239800129c61c7"
     }
   }
 ]
},
"queryHash" : "15D5A9A1",
"planCacheKey" : "1B1A4861",
"winningPlan" : {
 "stage" : "FETCH",
 "inputStage" : {
   "stage" : "IXSCAN",
   "keyPattern" : {
     "userId" : 1,
     "status" : 1
   },
   "indexName" : "userId_1_status_1",
   "isMultiKey" : false,
   "multiKeyPaths" : {
     "userId" : [ ],
     "status" : [ ]
   },
   "isUnique" : false,
   "isSparse" : false,
   "isPartial" : false,
   "indexVersion" : 2,
   "direction" : "forward",
   "indexBounds" : {
     "userId" : [
       "[\"59e022d33f239800129c61c7\", \"59e022d33f239800129c61c7\"]"
     ],
     "status" : [
       "[\"repayed\", \"repayed\"]"
     ]
   }
 }
},
"rejectedPlans" : [
 {
   "stage" : "FETCH",
   "filter" : {
     "status" : {
       "$eq" : "repayed"
     }
   },
   "inputStage" : {
     "stage" : "IXSCAN",
     "keyPattern" : {
       "userId" : 1
     },
     "indexName" : "userId_1",
     "isMultiKey" : false,
     "multiKeyPaths" : {
       "userId" : [ ]
     },
     "isUnique" : false,
     "isSparse" : false,
     "isPartial" : false,
     "indexVersion" : 2,
     "direction" : "forward",
     "indexBounds" : {
       "userId" : [
         "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
       ]
     }
   }
 }
]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren

(2) Andere Versuche
Interessanter Teil: Status trifft nicht auf den Index

db.loans.find({ "userId" : "59e022d33f239800129c61c7" }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "userId" : {
   "$eq" : "59e022d33f239800129c61c7"
 }
},
"queryHash" : "B1777DBA",
"planCacheKey" : "1F09D68E",
"winningPlan" : {
 "stage" : "FETCH",
 "inputStage" : {
   "stage" : "IXSCAN",
   "keyPattern" : {
     "userId" : 1
   },
   "indexName" : "userId_1",
   "isMultiKey" : false,
   "multiKeyPaths" : {
     "userId" : [ ]
   },
   "isUnique" : false,
   "isSparse" : false,
   "isPartial" : false,
   "indexVersion" : 2,
   "direction" : "forward",
   "indexBounds" : {
     "userId" : [
       "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
     ]
   }
 }
},
"rejectedPlans" : [
 {
   "stage" : "FETCH",
   "inputStage" : {
     "stage" : "IXSCAN",
     "keyPattern" : {
       "userId" : 1,
       "status" : 1
     },
     "indexName" : "userId_1_status_1",
     "isMultiKey" : false,
     "multiKeyPaths" : {
       "userId" : [ ],
       "status" : [ ]
     },
     "isUnique" : false,
     "isSparse" : false,
     "isPartial" : false,
     "indexVersion" : 2,
     "direction" : "forward",
     "indexBounds" : {
       "userId" : [
         "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
       ],
       "status" : [
         "[MinKey, MaxKey]"
       ]
     }
   }
 }
]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren

Wie wir vermutet haben, hat der Trefferindex nichts mit der Reihenfolge der Felder in der Abfrage zu tun.

Kommen wir zurück zum interessanten Teil: Wir löschen den Index {userId:1} besser, aber es gibt keinen Treffer. Zusammengesetzter Index, weil der Status nicht das führende Feld ist.

db.loans.find({ "status" : "repayed" }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "status" : {
   "$eq" : "repayed"
 }
},
"queryHash" : "E6304EB6",
"planCacheKey" : "7A94191B",
"winningPlan" : {
 "stage" : "COLLSCAN",
 "filter" : {
   "status" : {
     "$eq" : "repayed"
   }
 },
 "direction" : "forward"
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren
Ändern Sie den Sortierwinkel erneut und tauschen Sie ihn mit der vorherigen Abfrage und Sortierung aus. Die vorherige war:

db.loans.find({ "userId" : "59e022d33f239800129c61c7" }).sort({status:1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "userId" : {
   "$eq" : "59e022d33f239800129c61c7"
 }
},
"queryHash" : "F5ABB1AA",
"planCacheKey" : "764CBAA8",
"winningPlan" : {
 "stage" : "FETCH",
 "inputStage" : {
   "stage" : "IXSCAN",
   "keyPattern" : {
     "userId" : 1,
     "status" : 1
   },
   "indexName" : "userId_1_status_1",
   "isMultiKey" : false,
   "multiKeyPaths" : {
     "userId" : [ ],
     "status" : [ ]
   },
   "isUnique" : false,
   "isSparse" : false,
   "isPartial" : false,
   "indexVersion" : 2,
   "direction" : "forward",
   "indexBounds" : {
     "userId" : [
       "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
     ],
     "status" : [
       "[MinKey, MaxKey]"
     ]
   }
 }
},
"rejectedPlans" : [
 {
   "stage" : "SORT",
   "sortPattern" : {
     "status" : 1
   },
   "inputStage" : {
     "stage" : "SORT_KEY_GENERATOR",
     "inputStage" : {
       "stage" : "FETCH",
       "inputStage" : {
         "stage" : "IXSCAN",
         "keyPattern" : {
           "userId" : 1
         },
         "indexName" : "userId_1",
         "isMultiKey" : false,
         "multiKeyPaths" : {
           "userId" : [ ]
         },
         "isUnique" : false,
         "isSparse" : false,
         "isPartial" : false,
         "indexVersion" : 2,
         "direction" : "forward",
         "indexBounds" : {
           "userId" : [
             "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
           ]
         }
       }
     }
   }
 }
]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren

Sehen Sie, was der Unterschied ist?
db.loans.find({ "status" : "repayed","userId" : "59e022d33f239800129c61c7", }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "$and" : [
   {
     "status" : {
       "$eq" : "repayed"
     }
   },
   {
     "userId" : {
       "$eq" : "59e022d33f239800129c61c7"
     }
   }
 ]
},
"queryHash" : "15D5A9A1",
"planCacheKey" : "1B1A4861",
"winningPlan" : {
 "stage" : "FETCH",
 "inputStage" : {
   "stage" : "IXSCAN",
   "keyPattern" : {
     "userId" : 1,
     "status" : 1
   },
   "indexName" : "userId_1_status_1",
   "isMultiKey" : false,
   "multiKeyPaths" : {
     "userId" : [ ],
     "status" : [ ]
   },
   "isUnique" : false,
   "isSparse" : false,
   "isPartial" : false,
   "indexVersion" : 2,
   "direction" : "forward",
   "indexBounds" : {
     "userId" : [
       "[\"59e022d33f239800129c61c7\", \"59e022d33f239800129c61c7\"]"
     ],
     "status" : [
       "[\"repayed\", \"repayed\"]"
     ]
   }
 }
},
"rejectedPlans" : [
 {
   "stage" : "FETCH",
   "filter" : {
     "status" : {
       "$eq" : "repayed"
     }
   },
   "inputStage" : {
     "stage" : "IXSCAN",
     "keyPattern" : {
       "userId" : 1
     },
     "indexName" : "userId_1",
     "isMultiKey" : false,
     "multiKeyPaths" : {
       "userId" : [ ]
     },
     "isUnique" : false,
     "isSparse" : false,
     "isPartial" : false,
     "indexVersion" : 2,
     "direction" : "forward",
     "indexBounds" : {
       "userId" : [
         "["59e022d33f239800129c61c7", "59e022d33f239800129c61c7"]"
       ]
     }
   }
 }
]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren
Wie vermutet, klicken Sie auf den Index. Lass uns noch einmal spielen und den führenden eingereichten Test bestätigen:

db.loans.dropIndex("userId_1_status_1")
{ "nIndexesWas" : 2, "ok" : 1 }
Nach dem Login kopieren
db.loans.getIndexes()
[
{
"v" : 2,
"key" : {
 "id" : 1
},
"name" : "id_",
"ns" : "cashLoan.loans"
}
]
Nach dem Login kopieren
db.loans.createIndex({status:1, userId:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
Nach dem Login kopieren
db.loans.getIndexes()
[
{
"v" : 2,
"key" : {
 "id" : 1
},
"name" : "id_",
"ns" : "cashLoan.loans"
},
{
"v" : 2,
"key" : {
 "status" : 1,
 "userId" : 1
},
"name" : "status_1_userId_1",
"ns" : "cashLoan.loans"
}
]
Nach dem Login kopieren
Nach dem Login kopieren
db.loans.find({ "status" : "repayed" }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "status" : {
   "$eq" : "repayed"
 }
},
"queryHash" : "E6304EB6",
"planCacheKey" : "7A94191B",
"winningPlan" : {
 "stage" : "FETCH",
 "inputStage" : {
   "stage" : "IXSCAN",
   "keyPattern" : {
     "status" : 1,
     "userId" : 1
   },
   "indexName" : "status_1_userId_1",
   "isMultiKey" : false,
   "multiKeyPaths" : {
     "status" : [ ],
     "userId" : [ ]
   },
   "isUnique" : false,
   "isSparse" : false,
   "isPartial" : false,
   "indexVersion" : 2,
   "direction" : "forward",
   "indexBounds" : {
     "status" : [
       "["repayed", "repayed"]"
     ],
     "userId" : [
       "[MinKey, MaxKey]"
     ]
   }
 }
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren
db.loans.getIndexes()
[
{
"v" : 2,
"key" : {
 "id" : 1
},
"name" : "id_",
"ns" : "cashLoan.loans"
},
{
"v" : 2,
"key" : {
 "status" : 1,
 "userId" : 1
},
"name" : "status_1_userId_1",
"ns" : "cashLoan.loans"
}
]
Nach dem Login kopieren
Nach dem Login kopieren
db.loans.find({"userId" : "59e022d33f239800129c61c7", }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cashLoan.loans",
"indexFilterSet" : false,
"parsedQuery" : {
 "userId" : {
   "$eq" : "59e022d33f239800129c61c7"
 }
},
"queryHash" : "B1777DBA",
"planCacheKey" : "5776AB9C",
"winningPlan" : {
 "stage" : "COLLSCAN",
 "filter" : {
   "userId" : {
     "$eq" : "59e022d33f239800129c61c7"
   }
 },
 "direction" : "forward"
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "RMBAP",
"port" : 27017,
"version" : "4.1.11",
"gitVersion" : "1b8a9f5dc5c3314042b55e7415a2a25045b32a94"
},
"ok" : 1
}
Nach dem Login kopieren

看完这个试验,明白了 {userId:1, status:1} vs {status:1,userId:1} 的差别了吗?

PS:这个case 里面其实status 区分度不高,这里只是作为实例展示。

三、总结:

  • 注意使用上、使用频率上、区分高的/常用的在前面;
  • 如果需要减少索引以节省memory/提高修改数据的性能的话,可以保留区分度高,常用的,去除区分度不高,不常用的索引。
  • 学会用explain()验证分析性能:

DB 一般都有执行器优化的分析,MySQL & MongoDB 都是 用explain 来做分析。
语法上MySQL :

explain your_sql

MongoDB:

yoursql.explain()

总结典型:理想的查询是结合explain 的指标,他们通常是多个的混合:

  • IXSCAN  : 索引命中;
  • Limit  : 带limit;
  • Projection :  相当于非 select * ;
  • Docs Size less is better  ;
  • Docs Examined less is better ;
  • nReturned=totalDocsExamined=totalKeysExamined ;
  • SORT in index :sort 也是命中索引,否则,需要拿到数据后,再执行一遍排序;
  • Limit Array elements : 限定数组返回的条数,数组也不应该太多数据,否则schema 设计不合理。

彩蛋

文末,还有最开头1个问题没回答:如果我的索引改加的都加了,还不够快,怎么办?
留个悬念,之后再写一篇。

更多PHP相关技术文章,请访问PHP教程栏目进行学习!

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

Erklärung dieser Website
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

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was tun, wenn Navicat abläuft? Was tun, wenn Navicat abläuft? Apr 23, 2024 pm 12:12 PM

Zu den Lösungen zur Behebung von Navicat-Ablaufproblemen gehören: Erneuern der Lizenz; Deaktivieren der automatischen Updates; Wenden Sie sich an den Navicat-Kundendienst.

Ist es schwierig, NodeJS im Frontend zu lernen? Ist es schwierig, NodeJS im Frontend zu lernen? Apr 21, 2024 am 04:57 AM

Für Front-End-Entwickler hängt die Schwierigkeit, Node.js zu erlernen, von ihrer JavaScript-Grundlage, ihrer serverseitigen Programmiererfahrung, ihrer Vertrautheit mit der Befehlszeile und ihrem Lernstil ab. Die Lernkurve umfasst Module für Einsteiger und Fortgeschrittene, die sich auf grundlegende Konzepte, serverseitige Architektur, Datenbankintegration und asynchrone Programmierung konzentrieren. Insgesamt ist das Erlernen von Node.js für Entwickler, die über solide Kenntnisse in JavaScript verfügen und bereit sind, Zeit und Mühe zu investieren, nicht schwierig, aber für diejenigen, denen es an einschlägiger Erfahrung mangelt, müssen möglicherweise bestimmte Herausforderungen bewältigt werden.

So verbinden Sie Navicat mit Mongodb So verbinden Sie Navicat mit Mongodb Apr 24, 2024 am 11:27 AM

Um mit Navicat eine Verbindung zu MongoDB herzustellen, müssen Sie: Navicat installieren. Eine MongoDB-Verbindung erstellen: a. Geben Sie den Verbindungsnamen, die Hostadresse und den Port ein. b. Geben Sie die Authentifizierungsinformationen ein (falls erforderlich). Überprüfen Sie die Verbindung Speichern Sie die Verbindung

Was sind die am häufigsten verwendeten Module in NodeJS? Was sind die am häufigsten verwendeten Module in NodeJS? Apr 21, 2024 am 04:34 AM

Zu den am häufigsten verwendeten Modulen in Node.js gehören: Dateisystemmodul für Dateioperationen Netzwerkmodul für Netzwerkkommunikation Stream-Modul zur Verarbeitung von Datenströmen Datenbankmodul zur Interaktion mit Datenbanken Andere Hilfsmodule wie Verschlüsselung, Abfragezeichenfolgen, String-Analyse und HTTP-Framework

Welche Datenbank eignet sich für NodeJS? Welche Datenbank eignet sich für NodeJS? Apr 21, 2024 am 05:06 AM

Bei Node.js-Anwendungen hängt die Auswahl einer Datenbank von den Anwendungsanforderungen ab. Die NoSQL-Datenbanken MongoDB bieten Flexibilität, Redis bietet hohe Parallelität, Cassandra verarbeitet Zeitreihendaten und Elasticsearch ist auf die Suche spezialisiert. Die SQL-Datenbank MySQL bietet eine hervorragende Leistung, PostgreSQL ist reich an Funktionen, SQLite ist leichtgewichtig und Oracle Database ist umfassend. Berücksichtigen Sie bei der Auswahl Datentypen, Abfragen, Leistung, Transaktionalität, Verfügbarkeit, Lizenzierung und Kosten.

Wie NodeJS die Datenbank implementiert Wie NodeJS die Datenbank implementiert Apr 21, 2024 am 05:42 AM

Um eine Verbindung zu einer Datenbank in Node.js herzustellen, müssen Sie ein Datenbanksystem (relational oder nicht relational) auswählen und anschließend eine Verbindung mit für diesen Typ spezifischen Modulen herstellen. Zu den gängigen Modulen gehören MySQL (MySQL), PG (PostgreSQL), Mongodb (MongoDB) und Redis (Redis). Nachdem die Verbindung hergestellt wurde, können Sie Abfrageanweisungen zum Abrufen von Daten und Aktualisierungsanweisungen zum Ändern der Daten verwenden. Schließlich muss die Verbindung geschlossen werden, wenn alle Vorgänge abgeschlossen sind, um Ressourcen freizugeben. Verbessern Sie Leistung und Sicherheit, indem Sie diese Best Practices befolgen, z. B. die Verwendung von Verbindungspooling, parametrisierten Abfragen und eine ordnungsgemäße Fehlerbehandlung.

So verbinden Sie NodeJS mit der Datenbank So verbinden Sie NodeJS mit der Datenbank Apr 21, 2024 am 05:07 AM

Schritte zum Herstellen einer Verbindung zu einer Datenbank in Node.js: Installieren Sie das MySQL-, MongoDB- oder PostgreSQL-Paket. Erstellen Sie ein Datenbankverbindungsobjekt. Öffnen Sie eine Datenbankverbindung und behandeln Sie Verbindungsfehler.

Was nützt net4.0? Was nützt net4.0? May 10, 2024 am 01:09 AM

.NET 4.0 wird zum Erstellen einer Vielzahl von Anwendungen verwendet und bietet Anwendungsentwicklern umfangreiche Funktionen, darunter objektorientierte Programmierung, Flexibilität, leistungsstarke Architektur, Cloud-Computing-Integration, Leistungsoptimierung, umfangreiche Bibliotheken, Sicherheit, Skalierbarkeit, Datenzugriff und Mobilgeräte Entwicklungsunterstützung.

See all articles