MongoDB 批量添加索引,脚本批量修改数据方法论

版权声明:转载请注明出处! https://blog.csdn.net/Dream_bin/article/details/86586529

MongoDB批量处理

 

目录

一、       背景... 1

二、       处理... 1

1.     处理方式... 1

2.     知识点... 1

3.     脚本... 2

1)    单纯的添加脚本... 2

2)    根据条件添加脚本... 2

3)    检测索引脚本... 3

三、       效果... 3

四、       完善... 3

五、       总结... 4

 

 

   排查线上生产环境问题,发现集合followInfo库里头部分集合(user_info_*)uid没有添加索引。由于查询是根据uid查询,为处理性能方面考虑,需要对followInfo 集合中的集合添加uid索引(不是唯一性索引)。

实际情况如下:

  1. followInfo 是一个库,库里有user_info_*集合(256个)以及其他不同名字的集合
  2. user_info_* 集合有的已经添加uid索引,有的没有添加。
  3. 部分user_info_*集合因为暂时没有数据,故该集合没有被创建,256中个集合大概有十个左右这样子的集合没有被创建。
  4. 存在的集合大概多二百一十多个,且每个集合数据量非常少,大概是一万多条数据。(也就说需要给大约二百多万条件数据添加索引)

目的:为user_info_*集合添加uid索引,并且检测那个集合没有添加成功的逻辑。

  1. 处理方式:通过编写批量脚本对集合统一添加索引
  2. 知识点
  1. 获取数据库

use followInfo;

  1. 获取集合列表(使用变量进行保存)

var t=db.getCollectionNames();    

  1. 遍历集合列表

t.forEach(function(item){

  // TODO

}

  1. 判断集合是否存在

if(item.indexOf("user_info_") == 0) {   // 假如存在则为0

   // TODO

}

  1. 添加索引(添加索引一定要考虑实际情况添加!)

// 常规方式,当数据量大,或者线上有性能要求,且访问量大的情况下不可以用这种// 方式

db.getCollection(item).createIndex({ uid: NumberInt("1")}, { name: "uid",unique: false});

 

// background方式

db.getCollection(item).createIndex({ uid: NumberInt("1")}, { name: "uid", unique: false,background: true});

当给大量数据添加索引是,有可能会导致数据库阻塞。

原因如下:

MongoDB 锁是库级锁,建索引就是一个容易引起长时间写锁的问题,MongoDB 在前台建索引时需要占用一个写锁(而且不会临时放弃),如果集合的数据量很大,建索引通常要花比较长时间,特别容易引起问题。

解决的方法很简单,MongoDB 提供了两种建索引的访问,

一种是 background 方式,不需要长时间占用写锁。

另一种是非 background 方式,需要长时间占用锁。使用 background 方式就可以解决问题。 例如,为超大表 posts 建立索引, 千万不用使用。

db.posts.ensureIndex({uid : 1})

而应该使用

db.posts.ensureIndex({uid: 1}, {background: 1})

  1. 脚本
  1. 单纯的添加脚本

use followInfo;

var t=db.getCollectionNames()

t.forEach(function(item){

      print(item.indexOf("user_info_"))

      if(item.indexOf("user_info_") == 0) {

           db.getCollection(item).createIndex({ uid: NumberInt("1")}, { name: "uid",unique: false});

      }

   }

)

print("end !")

  1. 根据条件添加脚本(排除不存在的集合并初始化.)

use followInfo;

for(var i= 0 ;i<256;i++) {

   var str = 'user_info_'+ i;

   var temp = db.str.exists();

   if (temp == null) {

    db.getCollection(str).createIndex({ uid: NumberInt("1")}, { name: "uid",unique: false ,background: true });

 

   }

}

print("end !")

  1. 检测索引脚本

use followInfo;

var t=db.getCollectionNames()

t.forEach(function(item){

     var index =  db.getCollection(item).getIndexes();

     if(index.length >= 2){

        var temp = index[1]

        if(temp.name != null && temp.name != 'uid')

        print(item + "  create indexs false !")

     } else {

        print(item + "  create indexs false !")

     }

   }

)

print("end !")

执行之后应是会有这样的提示信息:

othercollection  create indexs false !     (ps : 没有uid索引的才会提示!)

end !

代表对othercollection  穿建脚本失败,othercollection 并不是本次处理的集合。

  • 效果

以上脚本通过在命令行(或者执行js )执行后可以修库总某个集合下的索引问题。

通过这样的思路,可以对库总结合做更多的操作,例如重建索引,删除索引等等操作。

查询指定集合命令:

db.collectionName.getIndexes()

查看指定集合状态信息

db.collectionName.stats();

  1. 脚本1跟2可以合并成一个脚本来写,这里为了分析知识点,减少理解的而复杂度故意拆分出两个脚本,在实际的运用过程中根据实际情况编写。
  2. 检测索引脚本

该脚本只是检测库中所有集合的脚本,假如某个集合没有uid集合时,会打印出 collectionName create indexs false !

可以改进只判断指定类型的集合。

N/A

若发现问题或者有更好的建议,请告诉我,不胜感激涕零!O(∩_∩)O哈哈~

猜你喜欢

转载自blog.csdn.net/Dream_bin/article/details/86586529