Mongo 主键和非主键索引,性能差距为啥这么大?

2017-11-10 15:08:16 +08:00
 hheedat

我往测试数据库里塞了 500 万 条数据

{_id:1,field:1}
{_id:2,field:2}
...
...
...
{_id:5000000,field:5000000}

field 上建立有索引

然后按照主键和 field 查询, 相当于

db.data4.find({_id:{$gte:4000000}}).limit(1)

和

db.data4.find({field:{$gte:4000000}}).limit(1)

可以看出,时间差距巨大,这是为啥?

10869 次点击
所在节点    MongoDB
23 条回复
hheedat
2017-11-10 15:18:31 +08:00
mongod -version
db version v3.4.3
git version: f07437fb5a6cca07c10bafa78365456eb1d6d5e1
OpenSSL version: OpenSSL 1.0.2l 25 May 2017
billion
2017-11-10 15:23:19 +08:00
这是因为在 MongoDB 里面,非主键的索引会被转换成主键索引。
nullcc
2017-11-10 15:27:41 +08:00
_id 是主键,一般来说主键索引是聚簇索引,field 是非主键索引,也叫二级索引,二级索引每个索引项内部还保存了主键值,对二级索引的使用在索引中找到相应的叶子节点后都会使用其主键进行主键索引,这样开销就多了
hheedat
2017-11-10 15:30:05 +08:00
@nullcc 哦,那和 MySQL 一样一样的,不过也不应该有这么大的性能差距吧?
hheedat
2017-11-10 15:30:42 +08:00
@nullcc 确切的说和 innodb 一样一样的
nullcc
2017-11-10 15:31:50 +08:00
@hheedat 虽说每个存储引擎实现可能有些差别,不过我觉得内部原理应该差不多,你可以 explain 一下看看,也再建立一个(_id, field)的联合索引做覆盖查询对比看看。
nullcc
2017-11-10 15:32:42 +08:00
@hheedat 对的,innodb 就是这样的,mangodb 有用过但是没研究太深
nullcc
2017-11-10 15:33:11 +08:00
@hheedat 是不是有查询缓存在?
janxin
2017-11-10 15:34:39 +08:00
你 explain 一下,因为你用了 gte
janxin
2017-11-10 15:35:27 +08:00
看错了,主键也是 gte,基本上就是 6# 的问题了
gzlock
2017-11-10 15:40:26 +08:00
楼主用的是什么 gui 管理?
hheedat
2017-11-10 16:00:21 +08:00
@nullcc 不是,换几个数字,效果一样
egen
2017-11-10 16:00:52 +08:00
500w 的记录数量一个 gte 需要 2s 不合理,这个速度几乎就是没有索引的速度
刚简单测试了一下本地一个 40w 记录的数据库,一个加索引的日期,搜索时间不到 0.001 秒,另外一个未加索引的,搜索时间 200ms 左右,时间比例上和 lz 的接近
hheedat
2017-11-10 16:01:02 +08:00
@janxin 能用到哦
hheedat
2017-11-10 16:01:38 +08:00
@gzlock rock mongo
egen
2017-11-10 16:06:53 +08:00
@hheedat #15 是否建立了 _id + field 的复合索引?建立了复合索引之后,单独搜索 field 是没法使用该索引的
hheedat
2017-11-10 16:12:21 +08:00
@egen 没有,就两个索引,都是单独的,如图所示
chenqh
2017-11-10 19:58:16 +08:00
是不是 int 和 long 的区别?
a342191555
2017-11-10 21:00:16 +08:00
感觉你的索引没有正确工作…
我在 MongoDB 里试了下,同样插入了 500W 条数据,索引和数据像这样:

查询_id 的速度:

查询 field 的速度:

然后把 field 的索引删掉,查询 field 的速度:

这个没有索引的时间和你的很像。另外,@chenqh 提出的 NumberInt 和 NumberLong 好像没有关系,虽然一开始我也是这么想的。。
nekuata
2017-11-10 22:11:42 +08:00
@hheedat 虽然没用过 mongo...
你的_id 是 normal index,field 是 2d index
而 @a342191555 的两个 key 都是 1,大概都是 normal index
可能 2d index 在这里不能用吧?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/405302

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX