Paginierung ist ein wichtiger Teil jeder Datenbankoperation, wenn es um große Datensätze geht. Es ermöglicht Ihnen, Daten in überschaubare Blöcke aufzuteilen und so das Durchsuchen, Verarbeiten und Anzeigen zu vereinfachen. MongoDB bietet zwei gängige Paginierungsmethoden: Offset-basiert und Cursor-basiert. Obwohl beide Methoden denselben Zweck erfüllen, unterscheiden sie sich erheblich in der Leistung und Benutzerfreundlichkeit, insbesondere wenn der Datensatz wächst.
Lassen Sie uns in die beiden Ansätze eintauchen und sehen, warum die Cursor-basierte Paginierung oft die Offset-basierte Paginierung übertrifft.
Offsetbasierte Paginierung ist unkompliziert. Es ruft eine bestimmte Anzahl von Datensätzen ab einem bestimmten Offset ab. Beispielsweise könnte die erste Seite die Datensätze 0–9 abrufen, die zweite Seite die Datensätze 10–19 und so weiter.
Diese Methode hat jedoch einen erheblichen Nachteil: Wenn Sie zu höheren Seiten wechseln, wird die Abfrage langsamer. Dies liegt daran, dass die Datenbank die Datensätze der vorherigen Seiten überspringen muss, was ein Durchsuchen dieser Datensätze erfordert.
Hier ist der Code für die offsetbasierte Paginierung:
async function offset_based_pagination(params) { const { page = 5, limit = 100 } = params; const skip = (page - 1) * limit; const results = await collection.find({}).skip(skip).limit(limit).toArray(); console.log(`Offset-based pagination (Page ${page}):`, results.length, "page", page, "skip", skip, "limit", limit); }
Cursorbasierte Paginierung, auch Keyset-Paginierung genannt, basiert auf einer eindeutigen Kennung (z. B. einer ID oder einem Zeitstempel), um durch die Datensätze zu paginieren. Anstatt eine bestimmte Anzahl von Datensätzen zu überspringen, wird der zuletzt abgerufene Datensatz als Referenzpunkt für den Abruf des nächsten Satzes verwendet.
Dieser Ansatz ist effizienter, da er die Notwendigkeit vermeidet, die Datensätze vor der aktuellen Seite zu scannen. Dadurch bleibt die Abfragezeit konsistent, unabhängig davon, wie tief Sie in den Datensatz vordringen.
Hier ist der Code für die Cursor-basierte Paginierung:
async function cursor_based_pagination(params) { const { lastDocumentId, limit = 100 } = params; const query = lastDocumentId ? { documentId: { $gt: lastDocumentId } } : {}; const results = await collection .find(query) .sort({ documentId: 1 }) .limit(limit) .toArray(); console.log("Cursor-based pagination:", results.length); }
In diesem Beispiel ist lastDocumentId die ID des letzten Dokuments der vorherigen Seite. Bei der Abfrage der nächsten Seite ruft die Datenbank Dokumente mit einer ID ab, die größer als dieser Wert ist, und gewährleistet so einen nahtlosen Übergang zum nächsten Satz von Datensätzen.
Sehen wir uns an, wie diese beiden Methoden bei einem großen Datensatz funktionieren.
async function testMongoDB() { console.time("MongoDB Insert Time:"); await insertMongoDBRecords(); console.timeEnd("MongoDB Insert Time:"); // Create an index on the documentId field await collection.createIndex({ documentId: 1 }); console.log("Index created on documentId field"); console.time("Offset-based pagination Time:"); await offset_based_pagination({ page: 2, limit: 250000 }); console.timeEnd("Offset-based pagination Time:"); console.time("Cursor-based pagination Time:"); await cursor_based_pagination({ lastDocumentId: 170000, limit: 250000 }); console.timeEnd("Cursor-based pagination Time:"); await client.close(); }
Warum die Indizierung wichtig istIm Leistungstest werden Sie feststellen, dass die offsetbasierte Paginierung mit zunehmender Seitenzahl länger dauert, während der Cursor -basierte Paginierung bleibt konsistent und ist daher die bessere Wahl für große Datensätze. Dieses Beispiel zeigt auch die Leistungsfähigkeit der Indizierung. Versuchen Sie, den Index zu entfernen und sehen Sie sich dann auch das Ergebnis an!
Im Kontext der Cursor-basierten Paginierung stellt der Index sicher, dass das Abrufen des nächsten Satzes von Dokumenten (basierend auf der Dokument-ID) schnell erfolgt und die Leistung nicht abnimmt, wenn der Sammlung weitere Dokumente hinzugefügt werden.
Abschluss
Hier ist die vollständige index.js, die Sie lokal ausführen können:
const { MongoClient } = require("mongodb"); const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri); client.connect(); const db = client.db("testdb"); const collection = db.collection("testCollection"); async function insertMongoDBRecords() { try { let bulkOps = []; for (let i = 0; i 0) { await collection.bulkWrite(bulkOps); console.log("? Inserted records till now -> ", bulkOps.length); } console.log("MongoDB Insertion Completed"); } catch (err) { console.error("Error in inserting records", err); } } async function offset_based_pagination(params) { const { page = 5, limit = 100 } = params; const skip = (page - 1) * limit; const results = await collection.find({}).skip(skip).limit(limit).toArray(); console.log(`Offset-based pagination (Page ${page}):`, results.length, "page", page, "skip", skip, "limit", limit); } async function cursor_based_pagination(params) { const { lastDocumentId, limit = 100 } = params; const query = lastDocumentId ? { documentId: { $gt: lastDocumentId } } : {}; const results = await collection .find(query) .sort({ documentId: 1 }) .limit(limit) .toArray(); console.log("Cursor-based pagination:", results.length); } async function testMongoDB() { console.time("MongoDB Insert Time:"); await insertMongoDBRecords(); console.timeEnd("MongoDB Insert Time:"); // Create an index on the documentId field await collection.createIndex({ documentId: 1 }); console.log("Index created on documentId field"); console.time("Offset-based pagination Time:"); await offset_based_pagination({ page: 2, limit: 250000 }); console.timeEnd("Offset-based pagination Time:"); console.time("Cursor-based pagination Time:"); await cursor_based_pagination({ lastDocumentId: 170000, limit: 250000 }); console.timeEnd("Cursor-based pagination Time:"); await client.close(); } testMongoDB();
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3