构建索引
绝大部分时间,我们都想在从部署到生产环境之前定义索引。这样允许随着数据的插入增量式构建索引。但是,也有两种情况,我们可能会选择事后构建索引。
-
第一种是当我们还没有发布到生产环境时导入大量数据。例如,必须把应用程序迁移到MongoDB并需要从数据仓库导入用户信息进来时,我们需要事先为用户数据创建索引,这样做可以从开始确保索引处于理想状态下的平衡度和压缩度。
-
第二种情况(更加显而易见)是当我们必须优化新查询时,在现有数据集上创建索引。当我们添加或者修改功能时会发生这个事情,而且是比我们想像的次数还多。假设我们允许用户使用username登录,所以要对username字段建立索引。然后我们又修改程序允许用户使用email来登陆;现在我们可能需要在email上简历第二个索引。注意这种情况,因为这样做需要重新考虑索引。
不管是为什么创建新索引,过程通常都不愉快。对于大型数据集,构建索引需要几个小时,甚至几天。当然我们可以通过MongoDB日志来监控构建索引的过程。
- 注意生命索引
因为声明索引非常简单,所以促发索引构建也非常简单。如果数据集足够大,构建过程会花费很长时间。在生产环境下,这可能是个噩梦,因为没有办法中止这个过程。如果确实发生了,可能要灾备到从服务器上。最谨慎的忠告是把索引构建当做数据库迁移一样对待,要格外小心。
备份
因为难以构建索引,所以有时候我们想备份它们。不幸的是,不是所有的备份方法都支持索引
例如,你也许尝试使用mongodump和mongorestore,但是这些构建只会保存集合和索引。这意味着运行mongorestore时,所有集合定义的索引只要备份过,都会重新创建恢复。
通常,如果数据集很大,构建这些索引花费的时间可能无法接受。
所以,如果想备份索引,可能要单独备份MongoDB数据文件。
何时不应该使用索引
提取较小的子数据集时,索引非常高效。也有一些查询不使用索引会更快。结果集在原集合中所占的比例越大,索引的速度就越慢,因为使用索引需要进行两次查找:一次是查找索引条目,一次是根据索引指针去查找相应的文档。而全表扫描只需要进行一次查找:查找文档。在最坏的情况下(返回集合内的所有文档),使用索引进行的查找次数会是全表扫描的两倍,效率会明显比全表扫描低很多。
可惜,并没有一个严格的规则可以告诉我们,如何根据数据大小、索引大小、文档大小以及结果集的平均大小来判断什么时候索引很有用,什么时候索引会降低查询速度。一般来说,如果查询需要返回集合内30%的文档(或者更多),那就应该对索引和全表扫描的速度进行比较。然而,这个数字可能会在2%~60%之间变动。
- 影响索引效率的属性
索引通常适用的情况 | 全表扫描通常适用的情况 |
---|---|
集合较大 | 集合较小 |
文档较大 | 文档较小 |
选择性查询 | 非选择性查询 |
参考文献: 《MongoDB权威指南(第2版)》 、《MONGODB实战 第2版》