MongoDB 线上实践指南-基础篇之支撑百亿级访问(三)

来源:互联网 发布:java时间戳是什么 编辑:程序博客网 时间:2024/06/08 08:14

MongoDB 线上实践指南-基础篇之支撑百亿级访问


索引

  • MongoDB 的组合索引使用策略与 MySQL 一致,遵循“最左原则”

  • 索引名称长度不要超过128字符

  • 应尽量综合评估查询场景,通过评估尽可能的将单列索引并入组合索引以降低所以数量,结合1,2点

【案例8】MongoDB的组合索引规则和MySQL一样,都遵循最左原理,假设一个组合索引为:{a:1,b:1,c:1},那么以下条件的查询是可以被用到的:
{a:1}
{a:1,b:2}
{a:1,b:2,c:3}
{}
以下条件的查询是不能用到索引的:
{b:1}
{b:1:c:2}
{c:2}
另外在设计索引的时候可以通过该原理减少索引的数目,如果需要通过{a:xxx}或{a:xxx,b:xxx}来进行查询,那么创建索引:
{a:1,b:1}
即可同时满足这两个查询场景而无需再单独创建{a:1}索引。

  • 在创建组合索引的时候,应评估索引中包含的字段,尽量将数据基数大的字段放在组合索引的前面

【案例9】某业务某场景下的查询十分缓慢,大概需要1.7秒左右,需要进行调优,该场景的查询和对应索引如下:
查询:{name:baidu,status:0}
索引:{status:1,name:1}
乍一看没什么问题,因为查询和索引十分匹配,但对该集合分析后发现该集合一共有150万文档,而status=0的有1499930由于这基本上占了99%的文档数目(数据基数很小),所以导致虽然使用了索引,但依然需要从149万行数据中找到name=baidu的数据但name字段则有大量不同的数据(数据基数很大),所以如果将该组合索引调整为name在前,该查询即可先通过name字段抽出较少的数据,再通过status进行过滤,就快了:
{name:1.status:1}调整后查询耗时降低到3~5毫秒。

  • 在数据量较大的时候,MongoDB 索引的创建是一个缓慢的过程,所以应当在上前线或数据量变得很大前尽量评估,按需创建会用到的索引

  • MongoDB 的索引创建是库级锁,在索引创建时该集合所在库不可读写,所以如需添加索引,请联系 DBA

【案例10】某业务MongoDB突然报警, DBA紧急排查发现业务自行在一个较大的集合(300万行数据)上创建了一个索引导致该集合所在的库整个锁死这是因为MongoDB的锁为库级锁,而索引的调整也会锁住整个库直到索引调整完毕,此时与该库有关的读写操作以及与该实例有关的整体的状态查询操作均会被阻塞,所以对于读写较大的实例这样创建索引是十分危险的,在MongoDB2.4中可以用一个参数来规避主库的索引创建 导致的阻塞:{‘background’:’true’},但当这一操作同步到从库后,从库将会前台执行,此时从库的读写会被阻塞,而在MongoDB2.6中, 该操作在从库也会同样被放入后台执行以达到同样不影响读写的目的,但是这个参数带来的新问题是:如果一个集合非常非常大,那么后台创建索引会变得很慢很慢,对于一些较为急迫的索引调整需求这是无法满足的。而DBA可以采用rolling的方式,通过循环切主,下线从库添加索引的方式为整个集群添加索引,所以为了业务的稳定、安全,开发切勿自行添加索引,以防阻塞口。

  • MongoDB 支持 TTL 索引,该索引能够按你的需要自动删除XXX秒之前的数据并会尽量选择在业务低峰期执行删除操作
  • 如果你存放的数据是地理位置信息,比如:经纬度数据。那么可以在该字段上添加 MongoDB 支持的地理索引:2d 及 2dsphere,但他们是不同的,混用会导致结果不准确

2d:只能用于点对点索引,适用于平面地图和时间连续的数据,比如非常适用于游戏地图【2dsphere:允许指定点、线和多边形。适用于地球表面类型的地图(球体) 】如果在球体表面创建2d索引,则会导致极点附近出现大量扭曲变形,最终导致结果不准确


  • MongoDB 的全文索引目前仍然处于“实验”阶段,性能并不够理想,当前不建议使用
  • 从 MongoDB2.4开始,支持索引的 ICP 功能,可以通过其合理减少索引数量

从 MongoDB2.4开始,组合索引能够被更有效的利用,如:
索引{x:1,y:1,z:1}可以被查询{x:1,z:1}所利用如果x字段的数据基数很大,而该条件匹配到的数据有很少,在这种情况下无需专门添加{x:1,z:1}索引,索引{x:1,y:1,z:1}即可带来理想的性能但需要注意的是,ICP 性能并没有原生的连续的组合索引效率好,如果发现效率不佳那么还是需要添加单独的{x:1,z:1}索引

0 0
原创粉丝点击