为什么mongodb性能在两个相似的分片中差异如此之大?

时间:2013-10-09 19:59:56

标签: performance mongodb sharding database-administration

我有两个碎片,每个碎片有三个复制机器(相同的规格)

这些块的分布相当合理:

Shard events at events/xxx:27018,yyy:27018
 data : 6.82GiB docs : 532402 chunks : 59
 estimated data per chunk : 118.42MiB
 estimated docs per chunk : 9023

Shard events2 at events2/zzz:27018,qqq:27018
 data : 7.3GiB docs : 618783 chunks : 66
 estimated data per chunk : 113.31MiB
 estimated docs per chunk : 9375

Totals
 data : 14.12GiB docs : 1151185 chunks : 125
 Shard events contains 48.29% data, 46.24% docs in cluster, avg obj size on shard : 13KiB
 Shard events2 contains 51.7% data, 53.75% docs in cluster, avg obj size on shard : 12KiB

然而,一方的主要部分几乎是vmsize的4倍,锁定%接近90%(另一方面为2%)以及更高的btree计数。这导致大量光标在该机器上超时。

两个分片都应该获得类似类型的查询,并且opcounter值非常接近。

sane host

problem host

我该如何诊断?

更新表现不佳的一方似乎正在为数​​据使用大量存储空间,包括索引空间的100倍:

    "ns" : "site_events.listen",
    "count" : 544213,
    "size" : 7500665112,
    "avgObjSize" : 13782.59084586366,
    "storageSize" : 9698657792,
    "numExtents" : 34,
    "nindexes" : 3,
    "lastExtentSize" : 1788297216,
    "paddingFactor" : 1.0009999991378065,
    "systemFlags" : 1,
    "userFlags" : 1,
    "totalIndexSize" : 4630807488,
    "indexSizes" : {
            "_id_" : 26845184,
            "uid_1" : 26664960,
            "list.i_1" : 4577297344
    },

VS

    "ns" : "site_events.listen",
    "count" : 621962,
    "size" : 7891599264,
    "avgObjSize" : 12688.233789202555,
    "storageSize" : 9305386992,
    "numExtents" : 24,
    "nindexes" : 2,
    "lastExtentSize" : 2146426864,
    "paddingFactor" : 1.0000000000917226,
    "systemFlags" : 1,
    "userFlags" : 1,
    "totalIndexSize" : 45368624,
    "indexSizes" : {
            "_id_" : 22173312,
            "uid_1" : 23195312
    },

1 个答案:

答案 0 :(得分:2)

根据更新的统计信息,很明显在分区集合的一个分片上存在一个索引,而另一个分片上没有。当以旋转方式在副本集上构建索引但有人忘记在两个分片上构建索引时,或者当它不应该在那里,但是没有从所有副本集中删除时,就会发生这种情况。

在您的情况下,额外索引“list.i_1”的大小为4.2GB,而且肯定会对性能差异产生重大影响。

我的其他评论更为一般,有些可能与您的示例无关。

一般来说,用户从一个分片(或非分片副本集)开始,然后添加第二个分片来承担一半的负载并不罕见。

不幸的是,数据迁移到shard2的方式使shard1留下了碎片存储,无论是数据还是索引。由于MongoDB使用内存映射文件,较大的文件最终使用更多的RAM,从而对I / O子系统造成更大的压力,并且通常比更紧凑的shard2性能更低,shard2基本上“同时”获得所有数据,并且能够使用更少的空间存储相似数量的文档。

如果有多个分片集合,您可以使用该程序将shard1恢复为压缩受影响的集合,甚至修复数据库()。后者会将释放的空间返回给操作系统,但即使压缩不会将空间返回给操作系统,它会将其保留在空闲列表中,以便在插入更多数据时使用,但现有数据将很好地共存在尽可能小的空间内。

请注意,在同一副本集中,即使其中一个原色 大于另一个原色,但辅助副本要小得多。如果次要“重新同步”其所有数据的时间远远晚于分片之间的平衡发生时,则会发生这种情况。在这种情况下,你可以降低你的主要,让更紧凑的二级接管 - 它应该表现更好,同时你可以压缩或修复前一个主要(新的二级)。通常,建议使用三个副本节点,以便在进行此类维护时不使用安全网。

我将做的另一个观察是,即使在两个分片上都有一个或多或少均匀分片的集合,你还有许多额外的集合存在于这个数据库的主分片上,这是更大的分片。索引大小的差异当然是由于shard1而不是shard2上存在的额外集合的额外索引。这对于只有一些集合进行分片的数据库来说是正常的。

除了:

之外,关于这种不平衡的问题并不多
  1. 分割较大的未整理的集合或
  2. 将一半未加密的集合移动到另一个数据库中,该数据库将shard2作为其主要分片。这将在两个分片之间更加“均匀”地分割未整理的集合。