MongoDB Shard Key的优化浅析

本篇文章真要针对MongoDB的官网上关于shardkey的选择:http://www.mongodb.org/display/DOCS/Choosing a ShardKey#1355。其中有一点叫做Index optimization:
Index optimization

As mentioned in other sections about indexing, it is usuallymuch better performance-wise if only a portion of the index isread/updated, so that this "active" portion can stay in RAM most ofthe time. Most shard keys described above result in an even spreadover the shards but also within each mongod's index. Instead, itcan be beneficial to factor in some kind of timestamp at thebeginning of the shard key in order to limit the portion of theindex that gets hit.
Say you have a photo storage system, with photo entries like:

{
   _id: ObjectId("4d084f78a4c8707815a601d7"),


   user_id : 42 ,
   

title: "sunset at the beach",


   upload_time : "2011-01-02T21:21:56.249Z" ,


   data: ...,
}

You could instead build a custom id that includes themonth of the upload time, and a unique identifier (ObjectId, MD5 ofdata, etc). Your entry now looks like:

{
   _id: "2011-01_4d084f78a4c8707815a601d7",


   user_id : 42 ,


   title: "sunset at the beach",


   upload_time : "2011-01-02T21:21:56.249Z" ,


   data: ...,
}

This custom id would be the key used for sharding, and also theid used to retrieve a document. It gives both a good spread acrossall servers, and it reduces the portion of the index hit on mostqueries.

这里要说的就是如何选择shard key来优化索引,注意是索引不是数据本身。

因为MongoDB直接使用linux的MMAP机制,没有专门管理哪些数据放入磁盘哪些放入内存。因此索引和真实数据都是同等地位,混在了一起放入内存中,如果放不下,就用LRU(操作系统应该用的这个算法)把老的置换出去,不区分索引还是真实数据,而我们的目的是尽量让索引留在内存中,因此出现了本文提到的索引优化。

那么如何进行索引优化呢?当数据量很大的时候,索引也会变得很大,不可能所有索引都放在内存里,那么就要设计索引的内容,让最近经常要用到的索引放在内存里,即这一小部分索引放在内存里就能够应付大多数的查询。

下面举个例子来说明这个问题。

索引基本都是B树的数据结构,如下图所示


如果索引字段是记录id,而id的内容是如图的字母,我们假设如下的场景:
1、最近的插入后的结构就是如图所示,
2、并且叶子节点都是最新插入的数据,
3、并且当前query的查询条件都是最近插入的数据,即叶子节点

那么每次查询都要访问中间的DH,QTX节点。如果能够让叶子节点尽量都集中在左数上,并且叶子节点变成了左树中间节点,这样,就没有多余要访问的中间节点了,全部的访问节点都集中在了左树上。

那么如何才能做到上述的目标呢?很简单,让索引字段id带上时间戳,如2011-03-M。这样,新插入的索引都是连续的,就自然集中到了一起。而上图因为索引字段id是字母,连续插入的id字母无关。

这个例子就解释了索引优化中,索引字段常常前面带上时间戳。

再回到MongoDB中,除了索引字段前面有时间戳之外,带什么样的时间戳也很重要,因为这个决定了是否能够分散写入压力。如果时间戳精确到了秒级,那么连续的数据将要写到同一个chunk里,导致局部过热。因此在MongoDB里,时间戳常常为天或者月。例如“月+随机数”,这样就是把一个月内的数据分散到各个shard上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值