MongoDB のインデックス再構築
- スタンドアロンモード
- クラスターモード/外部MongoDB
-
ストレージコンポーネントのコンテナに入ります。
docker exec -it $(docker ps | grep mingdaoyun-sc | awk '{print $1}') bash
- MongoDBサーバーにログインします(レプリカセットの場合はPRIMARYノードにログインしてください)。
-
mdwsrowsデータベース配下のユーザー定義インデックスを再構築するため、reIndex.jsスクリプトファイルを作成します。「reIndex.js」スクリプトファイルの内容
var targetDbName = "mdwsrows"; // 対象データベース// コレクションホワイトリスト(ホワイトリストに含まれるコレクションは再構築しません)var collectionWhitelist = ["discussion","rowrelations","workSheetRowTopic","workSheetTopic","wslogs"];// インデックスホワイトリスト(ホワイトリストに含まれるインデックスは再構築しません)var indexWhitelist = ["_id_","idx_ctime","idx_utime","uk_rowid","idx_tp_status","idx_thirdprimary"];// DateTimeフォーマット関数function formatDateTime() {var now = new Date();var utc8Time = new Date(now.getTime() + (8 * 60 * 60 * 1000));return utc8Time.toISOString().replace('Z', '+08:00');}// 出力フォーマット関数function printHeader(text) {print("\n" + "=".repeat(100));print(text);print("=".repeat(100));}function printSection(text) {print("\n" + "-".repeat(80));print(text);print("-".repeat(80));}function printTimedAction(time, action) {print(`\n[${time}] ${action}`);}// JSONをインデントして出力function formatJSON(obj, indent = 5) {return JSON.stringify(obj, null, 2).split('\n').map((line, i) => i === 0 ? line : ' '.repeat(indent) + line).join('\n');}// createIndexコマンドのフォーマットfunction formatCreateIndexCommand(collName, key, options) {return `db.${collName}.createIndex(${formatJSON(key)},\n ${formatJSON(options)})`;}function printCommand(command) {print(" └─ Execute:");print(" " + command);}function printCompletion(seconds) {print(` └─ ✓ Completed in ${seconds.toFixed(3)} seconds\n`);}// 対象データベースに接続var targetDb = db.getSiblingDB(targetDbName);var startTime = formatDateTime();printHeader("MongoDB Index Rebuild Process");print(`\n• Start Time: ${startTime}`);print(`• Target Database: ${targetDb.getName()}`);// ホワイトリストを除外し、再構築対象のコレクション一覧を取得var collections = targetDb.getCollectionNames().filter(function(collName) {return !collectionWhitelist.includes(collName) &&!collName.startsWith('system.');});print(`• Total Collections: ${collections.length}`);collections.forEach(function(collName, index) {var coll = targetDb.getCollection(collName);var stats = coll.stats();// コレクション情報・進捗を出力printSection(`Processing Collection [${index + 1}/${collections.length}]: ${collName}`);print(`\n• Document Count: ${stats.count}`);print(`• Storage Size: ${stats.storageSize} bytes`);// インデックスホワイトリストを除外し、再構築対象インデックスを取得var indexes = coll.getIndexes();var rebuildIndexes = indexes.filter(function(idx) {return !indexWhitelist.includes(idx.name);});if (rebuildIndexes.length === 0) {print("\n ✓ No indexes need to be rebuilt.");return;}// 再構築対象インデックスの出力print(`\n• Indexes to Rebuild (${rebuildIndexes.length}):`);rebuildIndexes.forEach(function(idx) {print(` ├─ Name: ${idx.name.padEnd(20)}`);print(` │ Key: ${JSON.stringify(idx.key)}`);});// 各インデックスを再構築rebuildIndexes.forEach(function(idx) {var key = idx.key;var options = {};// システム属性以外の設定をコピーfor (var prop in idx) {if (!["v", "ns", "background"].includes(prop)) {options[prop] = idx[prop];}}options.background = true; // バックグラウンドでインデックス作成try {// 既存インデックス削除var dropTime = formatDateTime();printTimedAction(dropTime, `Dropping Index: ${idx.name}`);printCommand(`db.${collName}.dropIndex("${idx.name}")`);var dropStart = new Date();coll.dropIndex(idx.name);var dropEnd = new Date();printCompletion((dropEnd - dropStart)/1000);// 新規インデックス作成var createTime = formatDateTime();printTimedAction(createTime, `Creating Index: ${idx.name}`);printCommand(formatCreateIndexCommand(collName, key, options));var createStart = new Date();coll.createIndex(key, options);var createEnd = new Date();printCompletion((createEnd - createStart)/1000);} catch (e) {print(` └─ ✗ Error: ${e.message}`);print(" Skipping this index...\n");}});});var endTime = formatDateTime();printHeader("Process Completed");print(`\n• End Time: ${endTime}`); -
スクリプトを実行します。
- MongoDB認証なし
- MongoDB認証あり
nohup mongo mongodb://127.0.0.1:27017/admin --quiet reIndex.js >> reIndex_output.log 2>&1 &- 実行ログは
reIndex_output.logファイルに 出力されます。
nohup mongo mongodb://root:password@127.0.0.1:27017/admin --quiet reIndex.js >> reIndex_output.log 2>&1 &mongoコマンドがPATHに無い場合、絶対パスを指定してください。- 実行ログは
reIndex_output.logファイルに出力されます。
-
ログを監視し、スクリプト完了まで待機します(
Process CompleteとEnd Timeで終了します)。 -
reIndexWithCmd.jsスクリプトを作成し、システムが依存する一部のインデックスを再構築します。「reIndexWithCmd.js」スクリプトファイルの内容
// ====================================================================// CONFIGURATION// ====================================================================// 対象となるデータベースおよび再構築を除外するコレクションを設定// 形式: "データベース名": ["除外コレクション1", "除外コレクション2"...]// 空配列 [] の場合は全コレクションが対象var targetDatabases = {"mdpost": [],"MDHistory": []};// ====================================================================// 出力フォーマット関数(変更不要)function printHeader(text) {print("\n" + "=".repeat(100));print(text);print("=".repeat(100));}function printSection(text) {print("\n" + "-".repeat(80));print(text);print("-".repeat(80));}function formatDateTime() {var now = new Date();var utc8Time = new Date(now.getTime() + (8 * 60 * 60 * 1000));return utc8Time.toISOString().replace('Z', '+08:00');}function formatJSON(obj, indent = 5) {if (obj === undefined || obj === null) {return "Not available";}return JSON.stringify(obj, null, 2).split('\n').map((line, i) => i === 0 ? line : ' '.repeat(indent) + line).join('\n');}function formatFileSize(bytes) {if (bytes === undefined || bytes === null) return "N/A";return (bytes / 1024 / 1024).toFixed(2) + " MB";}function printTimedAction(time, action) {print(`\n[${time}] ${action}`);}function printCompletion(seconds) {print(` └─ ✓ Completed in ${seconds.toFixed(3)} seconds\n`);}// ====================================================================// SCRIPT EXECUTION// ====================================================================var overallStartTime = formatDateTime();printHeader("MongoDB Multi-Database Index Rebuild Process Started");print(`\n• Overall Start Time: ${overallStartTime}`);print(`• Databases to Process: ${Object.keys(targetDatabases).join(', ')}`);// 各データベースごとに処理for (var dbName in targetDatabases) {if (targetDatabases.hasOwnProperty(dbName)) {printHeader(`Processing Database: [ ${dbName} ]`);// 対象DBへ接続var currentDb = db.getSiblingDB(dbName);// 現在のデータベースの除外コレクション一覧var excludedCollections = targetDatabases[dbName];print(`\n• Target Database: ${currentDb.getName()}`);print(`• Excluded Collections: ${formatJSON(excludedCollections)}`);// 全コレクション取得var collections = currentDb.getCollectionNames();// ブラックリスト・システムコレクション除外var validCollections = collections.filter(collection =>!excludedCollections.includes(collection) && !collection.startsWith('system.'));print(`• Total Collections to Process in this DB: ${validCollections.length}`);if (validCollections.length === 0) {print("\nNo collections to process in this database. Moving to the next one.");continue;}validCollections.forEach(function(collection, index) {try {// コレクション統計情報取得var stats = currentDb[collection].stats();// コレクション情報・進捗を出力printSection(`Processing Collection [${index + 1}/${validCollections.length}]: ${collection}`);print(`\n• Collection Statistics:`);print(` ├─ Storage Size: ${formatFileSize(stats.storageSize)}`);print(` └─ Document Count: ${(stats.count || 0).toLocaleString()}`);// インデックス情報取得var indexes = currentDb[collection].getIndexes();print(`\n• Current Indexes (${indexes.length}):`);indexes.forEach(function(idx, i) {const isLast = i === indexes.length - 1;print(` ${isLast ? '└' : '├'}─ Name: ${idx.name.padEnd(20)}`);print(` ${isLast ? ' ' : '│'} Key: ${formatJSON(idx.key)}`);});// reIndex実行var execTime = formatDateTime();printTimedAction(execTime, "Executing reIndex()");print(" └─ Execute:");print(` db.getSiblingDB('${dbName}').getCollection('${collection}').reIndex()`);var startExec = new Date();var result = currentDb[collection].reIndex();var endExec = new Date();if (result.ok === 1) {printCompletion((endExec - startExec)/1000);print("• Operation Results:");print(` ├─ Previous Index Count: ${result.nIndexesWas}`);print(` ├─ Current Index Count: ${result.nIndexes}`);if (result.operationTime !== undefined) {print(` ├─ Operation Time: ${formatJSON(result.operationTime)}`);} else {print(` ├─ Operation Time: Not available (non-replica set deployment)`);}if (result.$clusterTime !== undefined) {print(` └─ Cluster Time: ${formatJSON(result.$clusterTime)}`);} else {print(` └─ Cluster Time: Not available (non-replica set deployment)`);}} else {print(` └─ ✗ ReIndex failed: ${formatJSON(result)}`);}} catch (e) {print(` └─ ✗ Error: ${e.message}`);print(" Skipping this collection...\n");}});}}var overallEndTime = formatDateTime();printHeader("Process Completed");print(`\n• Overall End Time: ${overallEndTime}`); -
スクリプトを実行します。
- MongoDB認証なし
- MongoDB認証あり
nohup mongo mongodb://127.0.0.1:27017/admin --quiet reIndexWithCmd.js >> reIndexWithCmd_output.log 2>&1 &- 実行ログは
reIndexWithCmd_output.logファイルに出力されます。
nohup mongo mongodb://root:password@127.0.0.1:27017/admin --quiet reIndexWithCmd.js >> reIndexWithCmd_output.log 2>&1 &mongoコマンドがPATHに無い場合、絶対パスを指定してください。- 実行ログは
reIndexWithCmd_output.logファイルに出力されます。
-
ログを監視し、スクリプト完了まで待機します(ログ末尾に
Process CompleteおよびEnd Timeと出力されます)。