在副本集和分片集群上构建 MongoDB 索引
2024-04-19 13:16 abce 阅读(87) 评论(0) 编辑 收藏 举报1.限制
留有足够的内存来容纳工作集是非常重要的。不一定所有索引都要放在内存中。
在 v4.0 之前,索引键的限制应小于 1024 字节。从 v4.2 版开始,这一限制被取消。
索引名也是如此,在使用 fcv 4.0 及以下版本的数据库中,索引名的最大长度为 127 字节。在 db v4.2 和 fcv 4.2 中,这一限制有所减少。
任何给定的单个集合中只能创建 64 个索引。
2.副本集滚动构建索引
从 MongoDB 4.4 及更高版本开始,索引构建会在所有数据承载节点上同时进行。对于不能容忍索引构建导致性能问题的工作负载,我们可以采用滚动索引构建策略。
注:
·唯一索引
要使用以下过程创建唯一索引,必须在此过程中停止对集合的所有写入。如果无法在此过程中停止对集合的所有写入,请不要使用下面的过程。
·日志大小
确保 oplog 足够大,以便完成索引或重新索引操作,而不至于落后太多而无法赶上。
滚动构建的过程
(1)关闭一个辅助节点,用其它端口号,以 standalone 的方式重启。
在这一步,每次只关闭一个辅助节点。禁用配置文件中的复制参数,并将 disableLogicalSessionCacheRefresh 设置成 true:
net:
bindIp: localhost,<hostname(s)|ip address(es)>
port: 27217
# port: 27017
#replication:
# replSetName: myRepl
setParameter:
disableLogicalSessionCacheRefresh: true
只需要做以上的调整,其它参数保持不变。完成这一步后保存退出,并重启 mongodb 实例。
sudo systemctl start mongod
现在,mongodb 运行在 27217 端口上。
(2)构建索引
登录数据库,创建索引。例如:
mongo –port 27217 -u 'username' –authenticationDatabase admin
> use student
switched to db student
> db.studentData.createIndex( { StudentID: 1 } );
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
(3)以副本集成员的方式重启该节点
索引创建结束后,就可以将该节点加回副本集了。
重新使用第一步中被注释掉的参数,重启节点。
net:
bindIp: localhost,<hostname(s)|ip address(es)>
port: 27017
replication:
replSetName: myRepl
保存后重启。
sudo systemctl start mongod
这样,重启后又重新变成复制集的成员了。
(4)按照上面的步骤,重复操作剩余的辅助节点。
建议是等上一个辅助节点追上延迟后,再对下一个节点做操作。
(5)在主节点上创建索引
一旦所有辅助节点的索引构建活动结束,就使用与上述相同的流程在最后一个剩余节点上创建索引。
连接到主节点并发出 rs.stepDown();一旦成功降级,它就成为次节点,并选出新的主节点。按照步骤一至三建立索引即可。
3.分片集群滚动构建索引
分片集群滚动构建索引和副本集滚动构建方式类似。但是有以下不同点
(1)首先要先关闭均衡器。
为了在分片集群中以滚动方式创建索引,有必要停止均衡器,以免最终出现不一致的索引。
连接到 mongos 实例并运行 sh.stopBalancer() 来停用均衡器。
如果正在进行迁移,均衡器只会在正在进行的迁移完成后才会停止。
我们可以使用下面的命令检查均衡器是否已停止:
sh.getBalancerState()
如果均衡器已经被停止了,状态会是 false 。
(2)要确认集合的分布
为了以滚动的方式建立索引,有必要知道集合在哪些分片上。
连接到其中一个 mongos 并刷新缓存,这样我们就能获得要建立索引的分片内集合的最新分布信息。
示例:
我们要在学生数据库中的 studentData 集合中创建索引。我们将运行以下命令来获取该集合的最新分布信息。
db.adminCommand( { flushRouterConfig: "students.studentData" } );
db.records.getShardDistribution();
会获得如下类似的分片信息:
Shard shardA at shardA/s1-mongo1.net:27018,s1-mongo2.net:27018,s1-mongo3.net:27018
data : 1KiB docs : 50 chunks : 1
estimated data per chunk : 1KiB
estimated docs per chunk : 50
Shard shardC at shardC/s3-mongo1.net:27018,s3-mongo2.net:27018,s3-mongo3.net:27018
data : 1KiB docs : 50 chunks : 1
estimated data per chunk : 1KiB
estimated docs per chunk : 50
Totals
data : 3KiB docs : 100 chunks : 2
Shard shardA contains 50% data, 50% docs in cluster, avg obj size on shard : 40B
Shard shardC contains 50% data, 50% docs in cluster, avg obj size on shard : 40B
以看出,students.studentData 存在于 shardA 和 shardC 上,我们需要分别在 shardA 和 shardC 上建立索引。
(3)以 standalone 方式启动之前,还要注释掉分片相关的参数
涉及修改端口号、注释掉复制参数、分片参数、设置 disableLogicalSessionCacheRefresh: true
比如:
net:
bindIp: localhost,<hostname(s)|ip address(es)>
port: 27218
# port: 27018
#replication:
# replSetName: shardA
#sharding:
# clusterRole: shardsvr
setParameter:
skipShardingConfigurationChecks: true
disableLogicalSessionCacheRefresh: true
重启后创建索引
(4)最后要启动均衡器
sh.startBalancer()