MongoDB索引

本系列文章学习来源是技术胖的MogoDB系列

  索引的性能提高必须要有大量数据才能看出来,像我们之前操作数据库,用10条数据,是看不出来效果的,接下来通过随机数的方法,创造出一个百万级数据的数据库出来。

制作随机数:
  我们要想生成一个百万级的数据集合,必须要有随机数的参与,我们需要写一个随机数的方法。

//生成随机数
function GetRandomNum(min,max){
    let range = max-min;   //得到随机数区间
    let rand = Math.random(); //得到随机值
    return (min + Math.round(rand *range)); //最小值+随机数取整
}
console.log(GetRandomNum(10000,99999));

制作随机用户名:
  有了随机数的方法,我们就可以制作一个随机生成的用户名。目的是存在不同的用户名,方便我们测试查询速度。

//生成随机数
function GetRandomNum(min,max){
    let range = max-min;   //得到随机数区间
    let rand = Math.random(); //得到随机值
    return (min + Math.round(rand *range)); //最小值+随机数取整
}
// console.log(GetRandomNum(10000,99999));

//生成随机用户名
function GetRadomUserName(min,max){
    let tempStringArray= "123456789qwertyuiopasdfghjklzxcvbnm".split("");//构造生成时的字母库数组
    let outPuttext = ""; //最后输出的变量
    //进行循环,随机生产用户名的长度,这里需要生成随机数方法的配合
    for(let i=1 ;i

插入200万数据:
  有了生成随机数和随机用户名的方法,就可以生产百万级数据了。

var db = connect('user');
db.randomInfo.drop();
var  tempInfo = [];
for (let i=0;i<2000000;i++){
    tempInfo.push({
        username:GetRadomUserName(7,16),
        regeditTime:new Date(),
        randNum0:GetRandomNum(100000,999999),
        randNum1:GetRandomNum(100000,999999),
        randNum2:GetRandomNum(100000,999999),
        randNum3:GetRandomNum(100000,999999),
        randNum4:GetRandomNum(100000,999999),
        randNum5:GetRandomNum(100000,999999),
        randNum6:GetRandomNum(100000,999999),
        randNum7:GetRandomNum(100000,999999),
        randNum8:GetRandomNum(100000,999999),
        randNum8:GetRandomNum(100000,999999),
    })
}
db.randomInfo.insert(tempInfo);

  这个过程会持续几分钟,插入完成后,我们可以使用 db.randomInfo.count() 这个命令查看数据中的数据条数。查询后发现集合中已经有了200万条数据,可以进行索引的操作了,我们先来建立一个索引,然后看看它的查询性能到底提升了多少倍。

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

var startTime = new Date().getTime()  //得到程序运行的开始时间
var  db = connect('user')          //链接数据库
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')    //打印出运行时间

  [SUCCESS]This run time is:1153ms

【索引查询】
  为用户名(username)建立索引

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

  查看现有索引

db.randomInfo.getIndexes()

  建立一下索引大概会花费30s时间,查看结果


    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "user.randomInfo"
    },
    {
        "v" : 2,
        "key" : {
            "username" : 1
        },
        "name" : "username_1",
        "ns" : "user.randomInfo"
    }
]

  再次执行上面的查询,[SUCCESS]This run time is:8ms,这时候查询的时间缩短到了8ms左右,查询性能提升了大概150倍左右。
  无论是在关系型数据库还是文档数据库,建立索引都是非常重要的。同时,建立索引是要消耗硬盘和内存资源的,所以还是要根据程序需要进行建立了。MongoDB也给我们进行了限制,只允许我们建立64个索引值。

索引虽然很好用,但并不是所有情况都适合用索引的。

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

复合索引

  复合索引是两条以上的索引,前面我们已经把username字段建立了索引,现在把randNum0,这个字段也设置成索引。

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

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

db.randomInfo.getIndexes()

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

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

【两个索引同时查询】
  同时查询两个索引的值,看看性能如何。

var startTime=new Date().getTime();
var db = connect('user');
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');

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

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

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

  [Demo]this run time is 3ms,查询速度的确加快了。

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

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

  这里需要注意的是删除时填写的值,并不是我们的字段名称(key),而是我们索引查询表中的name值,也支持删除全部的索引。

db.randomInfo.dropIndexes()

全文索引

  有时候需要在大篇幅的文章中搜索关键词,MongoDB为我们提供了全文索引。
  我们先建立一个集合(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这个单词的记录,我们可以使用“-”减号来取消。

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

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

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

你可能感兴趣的:(MongoDB索引)