mongodb安全和优化

MongoDB默认没有密码,且只允许本地访问。如果开放外网访问,就一定要设置密码,否则会有安全隐患。


批量插入与逐条插入的性能对比:

    一条插入语句可能好事几毫秒,但这过程中网络传输的时间占了很大比例。IO(输入/输出)操作总是最耗费时间的,无论是硬盘IO还是网络IO。现在的宽带技术,上下行速度动辄每秒几百兆字节。如果使用MangoDB插入数据还在逐条插入,每一条几个字节,那可真是白白浪费了网络带宽。

        • 如果写到本地的MongoDB ,数据会在网卡中转一圈再存入硬盘。
        • 如果写到远程的MongoDB ,数据会先从本地网卡出去,然后经过网线,在电磁波、光信号、电信号之间进行转换,中间通过一层一层的交换机路由器,甚至海底光缆,绕地球一圈再进入目标服务器的网卡最后存入数据库。

    当然,批量插入要考虑多方面:

        1.(从redis等中)要插入的数据量非常大,全部丢到内存里超出了内存空间咋办?

        2.(redis中的)数据暂停添加,要过好长一阵才会继续添加咋办?

        3.假设redis中有1亿数据,读到第99999999条数据时,突然断电咋办?

        ......

    如果Redis中的数据是持续性数据,则会有新数据源源不断被加入到Redis中,每次添加之间的时间间隔从几毫秒到几小时不等。代码可以如下(python):

扫描二维码关注公众号,回复: 6578077 查看本文章

        图片.png

        • 第11行代码:增加了一个计数变量,通过第25行代码实现每获取一次Redis中的数据就让变量加1。
        • 第21行代码:在Redis为空的情况下,如果people_info_list中有数据,不论有多少数据,只要请求Redis的次数为1000的倍数,那么就批量插入数据库。这样做的好处是,保证people_info_list中的数据最多等待100秒就会被插入数据库。这里使用了“%”实现取余操作,“ get_count % 100。”的结果为get_count除以1000的余数。如果结果为0则表示get_count 正好是1000 的整数倍。

        • 第24行代码: 在本次发现Redis为空的情况下,暂停0.1秒,这样做可以显著降低CPU的占用。


插入与更新的性能对比:

    图片.png

    (注意:salary字段是字符串,不是整型)


    逐条更新代码如下(python):

        图片.png

        图片.png

        • 第7行代码:读取所有数据,并只输出“_id ”字段(默认输出〕和“ salary ”字段。
        • 第8行代码: 把“ salary ” 字段转换为整型数据。
        • 第10行代码: 根据“_id ”宇段把新的“ salary ”字段更新到数据库中。

        逐条更新19808条数据耗时68.7 秒,比逐条插入数据的时间还长!!!


    用插入数据代替更新数据:

        对于必需逐条更新大量数据的情况,也可以使用插入代替更新来提高性能。
        基本逻辑是: 把数据插入到另一个集合中, 然后删除原来的集合,再把新集合改名为原来的集合。

        图片.png

        • 第6~8行代码: 初始化两个连接,分别指向batch集合和update by _insert集合。

        • 第14行代码: 把更新以后的数据添加到新的列表中。
        • 第15行: 把新的列表批量插入数据库。
        更新119808条数据并插入新的集合中,耗时3秒。

        更新完成以后,删除原来的batch集合,再把新的集合update _by_insert改名为“ batch ”,就变相完成了数据的批量更新。


使用索引提高查询速度:

    在一个集合的数据量到达千万量级以后,查询速度会变得非常缓慢, 这时就需要使用索引来加快查询速度。
    索引是一种特殊的数据结构,它使用了能够快速遍历的形式记录了集合中数据的位置。
    如果不使用索引,则每一次查询数据MongoDB都会遍历整个集合;而如果使用了索引,则MongoDB会直接根据索引快速找到需要的内容。

        1. 索引的创建

            mongodb采用ensureIndex来创建索引,如:

            db.user.ensureIndex({"name":1})

            表示在user集合的name键创建一个索引,这里的1表示索引创建的方向,可以取值为1和-1

            在这里面,我们没有给索引取名字,mongodb会为我们取一个默认的名字,规则为keyname1_dir1_keyname2_dir2...keynameN_dirN

            keyname表示键名,dir表示索引的方向,例如,上面的例子我们创建的索引名字就是name_1

             

            索引还可以创建在多个键上,也就是联合索引,如:

            > db.user.ensureIndex({"name":1,"age":1})

            这样就创建了name和age的联合索引

            除了让mongodb默认索引的名字外,我们还可以去一个方便记的名字,方法就是为ensureIndex指定name的值,如:

            > db.user.ensureIndex({"name":1},{"name":"IX_name"})

            这样,我们创建的索引的名字就叫IX_name了

         

        2. 唯一索引

            与RDB类似,我们也可以定义唯一索引,方法就是指定unique键位true:

            >db.user.ensureIndex({"name":1},{"unique":true})

             

        3.查看我们建立的索引

            索引的信息存在每个数据库的system.indexes集合里面,对这个集合只能有ensureIndex和dropIndexes进行修改,不能手动插入或修改集合。

            通过> db.system.indexes.find()可以找到数据库中多有的索引:

            > db.system.indexes.find() 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.entities", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.blog", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.authors", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.papers", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.analytics", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.food", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user.info", "name" : "_id_" } 

            { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.userinfo", "name" : "_id_" } 

            { "v" : 1, "key" : { "name" : 1 }, "ns" : "test.user", "name" : "IX_name" }

         

        4.删除索引

            如果索引没有用了,可以使用dropIndexes将其删掉:

            > db.runCommand({"dropIndexes":"user","index":"IX_name"}) 

            { "nIndexesWas" : 2, "ok" : 1 }

            ok表示删除成功

猜你喜欢

转载自blog.51cto.com/5660061/2412421