MongoDB: 索引和复合索引以及全文索引(九)

集合中已经有了200万条的数据,可以进行索引的操作了。我们先来建立一个索引,然后看看它的查询性能到底提升了多少倍。这个不会很难,主要掌握索引的建立方法即可。

普通查询性能

我们先制作一个普通查询,随便查找一个用户名,并计算出查询和打印的时间,因为有200万条数据,所以性能不会很高。

var startTime = new Date().getTime()  //得到程序运行的开始时间
var  db = connect('company')          //链接数据库
var   rs=db.randomInfo.find({username:"tfruhjy8k"})  //根据用户名查找用户
rs.forEach(rs=>{printjson(rs)})                     //循环输出
var  runTime = new Date().getTime()-startTime;      //得到程序运行时间
print('[SUCCESS]This run time is:'+runTime+'ms')    //打印出运行时间

上边的代码就是一个普通的查询,只不过是记录了时间。在终端运行后,可以得到大概的运行时间是0.8秒左右(电脑性能不同,有所不同),第一次无缓存的运行时间大概是3.5秒左右。这个时间是没办法满足我们的日常查询的。

建立索引

试着为用户名(username)建立索引。建立索引只需要一句话就可以了。

db.randomInfo.ensureIndex({username:1})

查看现有索引

db.randomInfo.getIndexes()

终端的结果,现在只有一个索引值:

[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "company.randomInfo"
        }
]

那现在使用命令建立一下索引db.randomInfo.ensureIndex({uername:1}),我的电脑大概要50秒左右,建立好后我们重新使用db.randomInfo.getIndexes(),查看一下结果。

结果如下:已经变成了两条索引。

[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "company.randomInfo"
        },
        {
                "v" : 2,
                "key" : {
                        "username" : 1
                },
                "name" : "uername_1",
                "ns" : "company.randomInfo"
        }
]

然后我们在来load一下demo07.js文件(load(‘./demo07.js’)),看一下现在多少秒可以查询出来。这时候查询的时间缩短到了4ms左右,查询性能提升了大概200倍左右。

总结:无论是在关系型数据库还是文档数据库,建立索引都是非常重要的。前边讲了,索引这东西是要消耗硬盘和内存资源的,所以还是要根据程序需要进行建立了。MongoDB也给我们进行了限制,只允许我们建立64个索引值。

复合索引

索引中的小坑

记得我刚学MongoDB时,学会了索引,我就到处想用,甚至几百条数据的集合(collections),我也自作聪明的用一下,但结果往往是画蛇添足,走了不少弯路。通过实际开发和性能对比,我自己总结了几条不用索引的情况(不一定对,但是自己的经验之谈)。

  • 数据不超万条时,不需要使用索引。性能的提升并不明显,而大大增加了内存和硬盘的消耗。
  • 查询数据超过表数据量30%时,不要使用索引字段查询。实际证明会比不使用索引更慢,因为它大量检索了索引表和我们原表。
  • 数字索引,要比字符串索引快的多,在百万级甚至千万级数据量面前,使用数字索引是个明确的选择。
  • 把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引。

复合索引

好了上边我们讲了一大堆理论,现在来看复合索引。复合索引就是两条以上的索引。上节课我们已经把username字段建立了索引,我们现在把randNum0,这个字段也设置成索引。

db.randomInfo.ensureIndex({randNum0:1})

建立好后,我们再用查询索引状态命令进行查询。

db.randomInfo.getIndexes()

这时候已经是两个自建索引了,一共有三个索引。

[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "company.randomInfo"
        },
        {
                "v" : 2,
                "key" : {
                        "username" : 1
                },
                "name" : "username_1",
                "ns" : "company.randomInfo"
        },
        {
                "v" : 2,
                "key" : {
                        "randNum0" : 1
                },
                "name" : "randNum0_1",
                "ns" : "company.randomInfo"
        }
]

两个索引同时查询

我们同时查询两个索引的值,看看效果是怎么样的。

var startTime=new Date().getTime();
var db = connect('company');
var  rs= db.randomInfo.find({username:'7xwb8y3',randNum0:565509});
rs.forEach(rs=>{printjson(rs)});
var runTime = new Date().getTime()-startTime;
print('[Demo]this run time is '+runTime+'ms');

从性能上看并没有什么特殊的变化,查询时间还是在4ms左右。MongoDB的复合查询是按照我们的索引顺序进行查询的。就是我们用db.randomInfo.getIndexes()查询出的数组。

指定索引查询(hint)

数字的索引要比字符串的索引快,这就需要一个方法来打破索引表的查询顺序,用我们自己指定的索引优先查询,这个方法就是hint().

var  rs= db.randomInfo.find({username:'7xwb8y3',randNum0:565509}).hint({randNum0:1});

删除索引

当索引性能不佳或起不到作用时,我们需要删除索引,删除索引的命令是dropIndex().

db.randomInfo.dropIndex('randNum0_1');//索引的唯一ID

这里需要注意的是删除时填写的值,并不是我们的字段名称(key),而是我们索引查询表中的name值。这是一个小坑,希望小伙伴们不要踩中。

全文索引

准备工作:

这节我们先建立一个集合(collections)-info,然后插入一小段文章,作用就是为建立全文索引提供数据,当然我们不再建立百万级数据,我们只是看一下效果。

db.info.insert({contextInfo:"I am a programmer, I love life, love family. Every day after work, I write a diary."})
db.info.insert({contextInfo:"I am a programmer, I love PlayGame, love drink. Every day after work, I playGame and drink."}

当然这很简单,再次强调这只是文章需要,实际工作中这么简单的数据没必要建立全文索引。

建立全文索引

db.info.ensureIndex({contextInfo:'text'})

需要注意的是这里使用text关键词来代表全文索引,我们在这里就不建立数据模型了。

全文索引查找 建立好了全文索引就可以查找了,查找时需要两个关键修饰符:

  • $text:表示要在全文索引中查东西。
  • $search:后边跟查找的内容。

db.info.find({$text:{$search:"programmer"}})

查找多个词

全文索引是支持多个次查找的,比如我们希望查找数据中有programmer,family,diary,drink的数据(这是或的关系),所以两条数据都会出现。

db.info.find({$text:{$search:"programmer family diary drink"}})

如果我们这时候希望不查找出来有drink这个单词的记录,我们可以使用“-”减号来取消。

dbd .info.find({$text:{$search:"programmer family diary -drink"}})

转义符:

全文搜索中是支持转义符的,比如我们想搜索的是两个词(love PlayGame和drink),这时候需要使用\斜杠来转意。

db.info.find({$text:{$search:"\"love PlayGame\" drink"}})

全文索引在工作还是经常使用的,比如博客文章的搜索,长文件的关键词搜索,这些都需要使用全文索引来进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值