MongoDB索引

本系列文章學(xué)習(xí)來源是技術(shù)胖的MogoDB系列

??索引的性能提高必須要有大量數(shù)據(jù)才能看出來,像我們之前操作數(shù)據(jù)庫,用10條數(shù)據(jù),是看不出來效果的豪嗽,接下來通過隨機數(shù)的方法,創(chuàng)造出一個百萬級數(shù)據(jù)的數(shù)據(jù)庫出來。

制作隨機數(shù):
??我們要想生成一個百萬級的數(shù)據(jù)集合龟梦,必須要有隨機數(shù)的參與隐锭,我們需要寫一個隨機數(shù)的方法。

//生成隨機數(shù)
function GetRandomNum(min,max){
    let range = max-min;   //得到隨機數(shù)區(qū)間
    let rand = Math.random(); //得到隨機值
    return (min + Math.round(rand *range)); //最小值+隨機數(shù)取整
}
console.log(GetRandomNum(10000,99999));

制作隨機用戶名:
??有了隨機數(shù)的方法计贰,我們就可以制作一個隨機生成的用戶名钦睡。目的是存在不同的用戶名,方便我們測試查詢速度躁倒。

//生成隨機數(shù)
function GetRandomNum(min,max){
    let range = max-min;   //得到隨機數(shù)區(qū)間
    let rand = Math.random(); //得到隨機值
    return (min + Math.round(rand *range)); //最小值+隨機數(shù)取整
}
// console.log(GetRandomNum(10000,99999));

//生成隨機用戶名
function GetRadomUserName(min,max){
    let tempStringArray= "123456789qwertyuiopasdfghjklzxcvbnm".split("");//構(gòu)造生成時的字母庫數(shù)組
    let outPuttext = ""; //最后輸出的變量
    //進行循環(huán)荞怒,隨機生產(chǎn)用戶名的長度,這里需要生成隨機數(shù)方法的配合
    for(let i=1 ;i<GetRandomNum(min,max);i++){
        //隨機抽取字母秧秉,拼裝成需要的用戶名
        outPuttext=outPuttext+tempStringArray[GetRandomNum(0,tempStringArray.length)]
    }
    return outPuttext;
}
// console.log(GetRadomUserName(7,16))

插入200萬數(shù)據(jù):
??有了生成隨機數(shù)和隨機用戶名的方法褐桌,就可以生產(chǎn)百萬級數(shù)據(jù)了。

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);

??這個過程會持續(xù)幾分鐘象迎,插入完成后撩嚼,我們可以使用 db.randomInfo.count() 這個命令查看數(shù)據(jù)中的數(shù)據(jù)條數(shù)。查詢后發(fā)現(xiàn)集合中已經(jīng)有了200萬條數(shù)據(jù)挖帘,可以進行索引的操作了,我們先來建立一個索引恋技,然后看看它的查詢性能到底提升了多少倍拇舀。

【普通查詢】
??我們先制作一個普通查詢,隨便查找一個用戶名蜻底,并計算出查詢和打印的時間骄崩,因為有200萬條數(shù)據(jù),所以性能不會很高薄辅。

var startTime = new Date().getTime()  //得到程序運行的開始時間
var  db = connect('user')          //鏈接數(shù)據(jù)庫
var   rs=db.randomInfo.find({username:"tfruhjy8k"})  //根據(jù)用戶名查找用戶
rs.forEach(rs=>{printjson(rs)})                     //循環(huán)輸出
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})

??查看現(xiàn)有索引

db.randomInfo.getIndexes()

??建立一下索引大概會花費30s時間要拂,查看結(jié)果


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

??再次執(zhí)行上面的查詢,[SUCCESS]This run time is:8ms站楚,這時候查詢的時間縮短到了8ms左右脱惰,查詢性能提升了大概150倍左右。
??無論是在關(guān)系型數(shù)據(jù)庫還是文檔數(shù)據(jù)庫窿春,建立索引都是非常重要的拉一。同時,建立索引是要消耗硬盤和內(nèi)存資源的旧乞,所以還是要根據(jù)程序需要進行建立了蔚润。MongoDB也給我們進行了限制,只允許我們建立64個索引值尺栖。

索引雖然很好用嫡纠,但并不是所有情況都適合用索引的。

  • 數(shù)據(jù)不超萬條時,不需要使用索引除盏。性能的提升并不明顯叉橱,而大大增加了內(nèi)存和硬盤的消耗。
  • 查詢數(shù)據(jù)超過表數(shù)據(jù)量30%時痴颊,不要使用索引字段查詢赏迟。實際證明會比不使用索引更慢,因為它大量檢索了索引表和我們原表蠢棱。
  • 數(shù)字索引锌杀,要比字符串索引快的多,在百萬級甚至千萬級數(shù)據(jù)量面前泻仙,使用數(shù)字索引是個明智的選擇糕再。
  • 把你經(jīng)常查詢的數(shù)據(jù)做成一個內(nèi)嵌數(shù)據(jù)(對象型的數(shù)據(jù)),然后集體進行索引玉转。

復(fù)合索引

??復(fù)合索引是兩條以上的索引突想,前面我們已經(jīng)把username字段建立了索引,現(xiàn)在把randNum0究抓,這個字段也設(shè)置成索引猾担。

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

??建立好后,我們再用查詢索引狀態(tài)命令進行查詢刺下。

db.randomInfo.getIndexes()

??這時候已經(jīng)是兩個自建索引了绑嘹,一共有三個索引。

[
    {
        "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的復(fù)合查詢是按照索引順序進行查詢的,就是我們用db.randomInfo.getIndexes()查詢出的數(shù)組翁潘。

【指定索引查詢(hint)】
??數(shù)字的索引要比字符串的索引快趁冈,這就需要一個方法來打破索引表的查詢順序,用我們自己指定的索引優(yōu)先查詢拜马,這個方法就是hint().

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

??[Demo]this run time is 3ms箱歧,查詢速度的確加快了。

【刪除索引】
??當(dāng)索引性能不佳或起不到作用時一膨,我們需要刪除索引呀邢,刪除索引的命令是dropIndex()。

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

??這里需要注意的是刪除時填寫的值豹绪,并不是我們的字段名稱(key)价淌,而是我們索引查詢表中的name值申眼,也支持刪除全部的索引。

db.randomInfo.dropIndexes()

全文索引

??有時候需要在大篇幅的文章中搜索關(guān)鍵詞蝉衣,MongoDB為我們提供了全文索引括尸。
??我們先建立一個集合(collections) info,然后插入一小段文章病毡,作用就是為建立全文索引提供數(shù)據(jù)财饥。

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關(guān)鍵詞來代表全文索引恭垦,我們在這里就不建立數(shù)據(jù)模型了唤蔗。

查找時需要兩個關(guān)鍵修飾符:
$text:表示要在全文索引中查東西胃榕。
$search:后邊跟查找的內(nèi)容。

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

查找多個詞
??全文索引是支持多個詞查找的僧家,比如我們希望查找數(shù)據(jù)中有programmer雀摘,family,diary八拱,drink的數(shù)據(jù)(這是或的關(guān)系)阵赠,所以兩條數(shù)據(jù)都會出現(xiàn)。

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

??如果我們這時候希望不查找出來有drink這個單詞的記錄肌稻,我們可以使用“-”減號來取消清蚀。

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

轉(zhuǎn)義符
??全文搜索中是支持轉(zhuǎn)義符的,比如我們想搜索的是兩個詞(love PlayGame和drink)爹谭,這時候需要使用\斜杠來轉(zhuǎn)意枷邪。

db.info.find({$text:{$search:"\"love PlayGame\" drink"}})
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市旦棉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌药薯,老刑警劉巖绑洛,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異童本,居然都是意外死亡真屯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門穷娱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绑蔫,“玉大人,你說我怎么就攤上這事泵额∨渖睿” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵嫁盲,是天一觀的道長篓叶。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么缸托? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任左敌,我火速辦了婚禮,結(jié)果婚禮上俐镐,老公的妹妹穿的比我還像新娘矫限。我一直安慰自己,他們只是感情好佩抹,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布叼风。 她就那樣靜靜地躺著,像睡著了一般匹摇。 火紅的嫁衣襯著肌膚如雪咬扇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天廊勃,我揣著相機與錄音懈贺,去河邊找鬼。 笑死坡垫,一個胖子當(dāng)著我的面吹牛梭灿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冰悠,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼堡妒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溉卓?” 一聲冷哼從身側(cè)響起皮迟,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桑寨,沒想到半個月后伏尼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡尉尾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年爆阶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沙咏。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡辨图,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肢藐,到底是詐尸還是另有隱情故河,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布吆豹,位于F島的核電站忧勿,受9級特大地震影響杉女,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸳吸,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一熏挎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晌砾,春花似錦坎拐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呕乎,卻和暖如春积担,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猬仁。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工帝璧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人湿刽。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓的烁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诈闺。 傳聞我的和親對象是個殘疾皇子渴庆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容