Mongo 主键和非主键索引,性能差距为啥这么大? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hheedat
V2EX    MongoDB

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

  •  
  •   hheedat 2017-11-10 15:08:16 +08:00 11225 次点击
    这是一个创建于 2892 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    5000000

    field 上建立有索引

    index

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

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

    query1

    query2

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

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

    查询_id 的速度:

    查询 field 的速度:

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

    这个没有索引的时间和你的很像。另外,@chenqh 提出的 NumberInt 和 NumberLong 好像没有关系,虽然一开始我也是这么想的。。
    nekuata
        20
    nekuata  
       2017-11-10 22:11:42 +08:00
    @hheedat 虽然没用过 mongo...
    你的_id 是 normal index,field 是 2d index
    而 @a342191555 的两个 key 都是 1,大概都是 normal index
    可能 2d index 在这里不能用吧?
    a342191555
        21
    a342191555  
       2017-11-11 09:39:44 +08:00 via iPhone
    @nekuata 你的 field 也不是一个地理坐标呀。另外,dn.data4.getIndexes()返回什么?
    a342191555
        22
    a342191555  
       2017-11-11 09:41:00 +08:00 via iPhone
    @nekuata sry,把你当成 lz 了。在描述中我也没有看到 field 是 2d idx 呀
    nekuata
        23
    nekuata  
       2017-11-11 11:11:07 +08:00 via Android
    @a342191555 呃,不好意思看错了,索引图上面应该是按钮...
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1159 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 17:48 PVG 01:48 LAX 10:48 JFK 13:48
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86