如何优化跨多个数据库的 MongoDB 连接以加快搜索速度?

问题描述 投票:0回答:1

我正在开发一个涉及连接到多个 MongoDB 数据库(每个数据库包含大约 300 万用户)的项目。我并行连接到所有这些数据库并在这些数据库中执行搜索。然而,我觉得这个过程比预期的要慢。下面是我写的代码。

config.js(包含数据库的 URL)

export const dbURLs = [
  // TODO: Refactor this approach
  // Each URL has 3 million of Users
  process.env.DATABASE_URL_1,
  process.env.DATABASE_URL_2,
  process.env.DATABASE_URL_3,
  process.env.DATABASE_URL_4,
  process.env.DATABASE_URL_5,
  process.env.DATABASE_URL_6,
  process.env.DATABASE_URL_7,
  process.env.DATABASE_URL_8,
  process.env.DATABASE_URL_9,
  process.env.DATABASE_URL_10,
  process.env.DATABASE_URL_11,
  process.env.DATABASE_URL_12,
  process.env.DATABASE_URL_13,
  process.env.DATABASE_URL_14,
  process.env.DATABASE_URL_15,
  process.env.DATABASE_URL_16,
  process.env.DATABASE_URL_17,
  process.env.DATABASE_URL_18,
];

db.js(并行建立与所有数据库的连接)

async function connectToDatabases() {
  const databases = [];
  
  // Connecting in parallel
  await Promise.all(
    dbURLs.map(async (url, index) => {
      try {
        const client = new MongoClient(url, {
          maxPoolSize: 19,
          minPoolSize: 1,
        });
        await client.connect();
        const db = client.db(dbName);
        databases.push(db);
        console.log(`Successfully connected: ${index}`);
      } catch (error) {
        console.error(`Failed to connect to database at ${index}: ${error.message}`);
      }
    })
  );
  
  return databases;
}

searchController.js(在所有数据库中搜索特定用户)

const databases = await connectToDatabases();
let accountFound = false;
let accounts = [];

for (const db of databases) {
  const collection = db.collection(collectionName);
  const account = await collection.find({ id: facebook_id }).toArray();
  if (account.length > 0) {
    accountFound = true;
    accounts.push(...account);
    break;
  }
}
// other code

是否有更有效的方法来处理这些数据库之间的连接和搜索?

如何减少连接和查询数据库的时间?

javascript node.js mongodb performance mongoose
1个回答
0
投票

首先,您必须考虑为同一类型的数据拥有多个数据库。也许决定将单个数据库拆分为多个数据库,以便在不同的机器上分发数据。如果是这样,我可以给出一条考虑 MongoDB 分片功能的建议:https://www.mongodb.com/docs/manual/sharding/

第二,我坚持将连接初始化移至应用程序的初始化阶段,而不是在请求时执行连接。这样您就可以在请求时使用连接,而无需花费宝贵的时间进行初始化。另外,这样您就可以消除“内存泄漏”,因为一旦创建连接,它将被保留直到被释放,因此最佳实践是在启动时保留连接并在应用程序关闭时释放它们。否则,每个请求都会保留越来越多的连接,直到达到其限制:https://www.mongodb.com/docs/manual/reference/limits/

下一步

,确保您的集合(在您使用的每个数据库中)都有 id 字段的索引。相反,它会导致巨大的性能问题。从单字段索引开始:https://www.mongodb.com/docs/manual/core/indexes/index-types/index-single/#std-label-indexes-single-field

下一步

,考虑分页。我明白了,您使用 .toArray 方法立即通过网络从数据库中获取

all
文档。如果这就是您所需要的,如果您的文档包含更多数据,我可以建议添加一些投影(https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/)它是必需的,以便您可以减少通过网络传输的字节量。

最后

,您的代码不执行并行搜索。此外,一旦你的代码找到至少一个用户,你的代码就会停止搜索——这是故意的吗?如果没有,您可以通过以下方式显着提高性能(并使代码更小): const cursors = databases.map((db) => { const collection = db.collection(collectionName); return collection.find({ id: facebook_id }).toArray(); }); const accounts = await Promise.all(cursors); cursors.forEach((cursor) => cursor.close());

P.S.

请注意,根据文档(https://www.mongodb.com/docs/drivers/node/current/fundamentals/crud/read-operations/cursor/#close),您必须关闭您的游标以避免内存和网络泄漏

© www.soinside.com 2019 - 2024. All rights reserved.