面试题答案
一键面试在使用MongoDB为物联网海量数据存储场景设计片键时,需考虑以下要点以避免设计陷阱:
- 基于时间序列特性:
- 原理:物联网数据时间序列特征明显,时间戳是数据的关键属性。按时间进行分片,能将近期高频写入的数据分散到不同片上,避免单个片成为写入瓶颈。
- 示例:选择时间戳字段(如
timestamp
)作为片键的一部分。若数据按天产生,可将日期作为片键,如{timestamp: 1}
(1表示升序)。这样,不同日期的数据会分布在不同片上,随着时间推移,新数据不断分散写入。
- 避免热点问题:
- 原理:如果片键选择不当,如选择一个重复值多的字段(如设备类型中某类占比极大),会导致大部分数据集中在少数片上,形成热点,降低写入性能。
- 示例:不建议仅使用设备ID作为片键,因为可能存在某几个设备数据量远大于其他设备的情况,导致写入热点。应结合其他字段,如
{deviceId: 1, timestamp: 1}
,通过设备ID和时间戳共同分片,分散数据写入。
- 考虑查询模式:
- 原理:设计片键要兼顾查询需求。若经常按设备ID和时间范围查询数据,将这两个字段组合作为片键,能提高查询效率。
- 示例:若查询语句为
db.iotData.find({deviceId: "device123", timestamp: {$gte: "2023 - 01 - 01", $lte: "2023 - 01 - 31"}})
,片键设计为{deviceId: 1, timestamp: 1}
,查询时可快速定位到包含相关数据的片。
- 选择离散性好的字段:
- 原理:片键字段的值应具有良好的离散性,能均匀分布数据。离散性差的字段会使数据分布不均。
- 示例:避免使用取值范围小且重复率高的枚举字段作为片键。如设备状态字段(取值仅为“运行”“故障”“停止”),若以此为片键,数据易集中在某几个片上。应选择像设备唯一序列号这类离散性好的字段结合时间戳等作为片键。