分区数据均衡

    用户可以通过明确数据用途,合理利用分区,以此提高 SQL 执行效率。根据数据的用途不同,可以将数据分为三类:配置类数据、信息类数据和流水类数据。

    • 配置类数据: 配置类数据存储系统运行所需的各种配置信息。配置类数据是系统运行的基础,但数据量较少,适合存储在单节点。

    • 信息类数据: 记录固有信息的数据。该类数据特点为数据量较大,数据操作主要为查询和修改,新增数据一般较少。适合存储在多个节点。例:用户信息数据、资产信息数据。

    • 流水类数据: 按照时间先后顺序记录每一次交易的数据。该类数据特点为数据量初始较少,增量大。适合存储在方便动态扩容的节点。例:交易流水数据、日志流水数据。

    数据域的合理划分可以进行良好的数据分布控制,提升访问效率,优化数据库性能。数据域的规划需要根据系统内集合的职能进行规划,因此可以将数据域规划为三类。

    • 信息数据域:信息数据域中数据量较多,但增量较少,单集合数据量为数千万条,包含三个数据组到五个数据组,存储信息类数据。

    • 流水数据域:流水数据域中数据量很多,增量大,包含其余所有数据组,是以后扩容的重点关注域,存储流水类数据。

    定义了每个集合中所包含数据的分区规则。每一个集合对应一个分区键,分区键中可以包含一个或多个字段。集合和用途的不同决定了分区键的选择方式有所不同。

    数据是否均衡,可以从集合空间级别和集合级别这两个级别判断。集合空间级别可以定位集合空间内数据是否失衡并作为参考数据,详细的数据均衡判断需要在集合级别进行。

    • 数据均衡示例
    • 数据失衡示例
    1. -rw-r-----. 1 sdbadmin sdbadmin_group 277M Jun 5 02:26 /opt/sequoiadb/database/data/11820/test.1.data
    2. -rw-r-----. 1 sdbadmin sdbadmin_group 145M Jun 5 02:26 /opt/sequoiadb/database/data/11820/test.1.idx
    3. -rw-r-----. 1 sdbadmin sdbadmin_group 277M Jun 5 02:26 /opt/sequoiadb/database/data/11830/test.1.data
    4. -rw-r-----. 1 sdbadmin sdbadmin_group 145M Jun 5 02:26 /opt/sequoiadb/database/data/11830/test.1.idx
    5. -rw-r-----. 1 sdbadmin sdbadmin_group 533M Jun 5 02:26 /opt/sequoiadb/database/data/11840/test.1.data
    6. -rw-r-----. 1 sdbadmin sdbadmin_group 273M Jun 5 02:26 /opt/sequoiadb/database/data/11840/test.1.idx
    7. -rw-r-----. 1 sdbadmin sdbadmin_group 277M Jun 5 02:26 /opt/sequoiadb/database/data/11850/test.1.data
    8. -rw-r-----. 1 sdbadmin sdbadmin_group 145M Jun 5 02:26 /opt/sequoiadb/database/data/11850/test.1.idx

    集合级别

    集合级别的数据均衡判断需要根据集合在不同数据节点的数据条数进行判断。通过 db.snapshot() 获取集合快照,根据各数据组的 TotalRecords 值差距来判断数据是否均衡。

    • 数据均衡示例
    1. > db.snapshot(SDB_SNAP_COLLECTIONS, {Name:"test.balance"})
    2. {
    3. "Name": "test.balance",
    4. "UniqueID": 12884901907,
    5. "Details": [
    6. {
    7. "GroupName": "group1",
    8. "Group": [
    9. {
    10. "ID": 1,
    11. "LogicalID": 2,
    12. "Sequence": 1,
    13. "Indexes": 1,
    14. "Status": "Normal",
    15. "TotalRecords": 599207,
    16. "TotalDataPages": 1245,
    17. "TotalIndexPages": 297,
    18. "TotalLobPages": 0,
    19. "TotalDataFreeSpace": 90536,
    20. "TotalIndexFreeSpace": 2015437,
    21. "NodeName": "test:11820"
    22. }
    23. ]
    24. },
    25. {
    26. "GroupName": "group2",
    27. "Group": [
    28. {
    29. "ID": 0,
    30. "LogicalID": 1,
    31. "Sequence": 1,
    32. "Indexes": 1,
    33. "Status": "Normal",
    34. "TotalRecords": 600950,
    35. "TotalDataPages": 1235,
    36. "TotalIndexPages": 298,
    37. "TotalLobPages": 0,
    38. "TotalIndexFreeSpace": 2030405,
    39. "NodeName": "test:11830"
    40. }
    41. ]
    42. },
    43. {
    44. "GroupName": "group3",
    45. "Group": [
    46. {
    47. "ID": 0,
    48. "LogicalID": 1,
    49. "Sequence": 1,
    50. "Status": "Normal",
    51. "TotalRecords": 599843,
    52. "TotalDataPages": 1246,
    53. "TotalIndexPages": 297,
    54. "TotalLobPages": 0,
    55. "TotalDataFreeSpace": 87764,
    56. "TotalIndexFreeSpace": 1996993,
    57. "NodeName": "test:11840"
    58. }
    59. ]
    60. }
    61. ]
    62. }
    63. Return 1 row(s).
    64. Takes 0.012431s.
    • 数据失衡示例

    数据失衡时,用户需要确认集合的分区键和现有数据在分区键字段上的值,确认数据失衡原因。同时了解集合整体结构,重新选择分区键。

    • 查看数据失衡集合的分区键
    1. > db.snapshot(SDB_SNAP_CATALOG, {Name:"test.nobalance"})
    2. {
    3. "_id": {
    4. "$oid": "5cef6f39c07175a73358f64a"
    5. },
    6. "Name": "test.nobalance",
    7. "UniqueID": 12884901909,
    8. "Version": 4,
    9. "ReplSize": -1,
    10. "Attribute": 1,
    11. "AttributeDesc": "Compressed",
    12. "CompressionType": 1,
    13. "CompressionTypeDesc": "lzw",
    14. "ShardingKey": {
    15. "status": 1
    16. },
    17. "EnsureShardingIndex": false,
    18. "ShardingType": "hash",
    19. "Partition": 4096,
    20. "InternalV": 3,
    21. "CataInfo": [
    22. {
    23. "ID": 0,
    24. "GroupID": 1000,
    25. "GroupName": "group1",
    26. "LowBound": {
    27. "": 0
    28. },
    29. "UpBound": {
    30. "": 1365
    31. }
    32. },
    33. {
    34. "ID": 1,
    35. "GroupID": 1001,
    36. "GroupName": "group2",
    37. "LowBound": {
    38. "": 1365
    39. "UpBound": {
    40. "": 2730
    41. }
    42. },
    43. {
    44. "ID": 2,
    45. "GroupName": "group3",
    46. "LowBound": {
    47. "": 2730
    48. },
    49. "UpBound": {
    50. "": 4096
    51. }
    52. }
    53. ],
    54. "AutoSplit": true
    55. }
    56. Return 1 row(s).
    57. Takes 0.007257s.
    • 集合 test.nobalance 现有分区键为 status,查看现有数据中分区字段的值
    1. > db.test.nobalance.find({},{account:null,age:null,status:null}).limit(5)
    2. {
    3. "account": D00005,
    4. "age": 26,
    5. "status": "正常"
    6. }
    7. {
    8. "account": D00006,
    9. "age": 27,
    10. "status": "正常"
    11. }
    12. {
    13. "account": D00008,
    14. "age": 29,
    15. "status": "正常"
    16. }
    17. {
    18. "account": D00009,
    19. "age": 20,
    20. "status": "正常"
    21. }
    22. {
    23. "account": D00012,
    24. "age": 20,
    25. "status": "正常"
    26. }
    27. Return 5 row(s).
    28. Takes 0.001466s.
    • 创建临时集合 nobalance_temp ,以字段 account 为分区键
    • 导出 nobalance 集合中的数据
    1. $ sdbexprt --hostname localhost --svcname 11810 --type json --dir ./ --cscl test.nobalance
    2. Exported successfully with 1 successful collections, 1800000 successful records
    3. done!
    • 数据导入 nobalance_temp 集合
    1. $ sdbimprt --hosts=localhost:11810 --type=json -c test -l nobalance_temp --file=test.nobalance.json
    2. parsed records: 1800000
    3. parse failure: 0
    4. sharding records: 1800000
    5. sharding failure: 0
    6. imported records: 1800000
    7. import failure: 0
    • 确认数据分布是否均衡
    • 数据分布均衡后,集合 nobalance 改名为 nobalance_bak ,集合 nobalance_temp 改名为 nobalance
    1. > db.test.renameCL("nobalance", "nobalance_bak");
    2. Takes 0.031626s.
    3. > db.test.renameCL("nobalance_temp", "nobalance");