先举个例子,我用MongoDB 存储天气数据,格式大概是下面的样子:
[{ "_id": "ObjectId(\"5fcdf576b65c60d7fd7f2626\")", "Station": "1234567890", "DataTime": "2021-04-20 09:27:00", "Datas": [{ "Factor": "Temperature", "Value": 20.3, "Unit": "℃" }, { "Factor": "Temperature", "Value": 50.3, "Unit": "℉ " }, { "Factor": "Humidity", "Value": 1, "Unit": "%" }] }, { "_id": "ObjectId(\"5fcdf576b65c60d7fd7f2626\")", "Station": "1234567891", "DataTime": "2021-04-20 09:27:00", "Datas": [{ "Factor": "Temperature", "Value": 20.3, "Unit": "℃" }, { "Factor": "湿度", "Value": 1, "Unit": "%" }] } ]
数据每个Station每分钟1条,500个station,其中Datas是个数组(里面大概有100个以上的对象),因为有的station采集的因子数量不同,所以,就做成了数组嵌套了起来,跑了一个多月,查询起来很慢。尤其是查询这这500个station的1小时内的数据,用于计算平均值就更慢的离谱了,光查询就得有5,6分钟的样子,求大佬指教。
查询代码如下:
var list = collection.Find(x => x.DataTime <= DateTime.Parse("2021-03-29 17:59:00") && x.DataTime >= DateTime.Parse("2021-03-29 17:00:00")) .Project(c => new RealTimeData { Id = c.Id, DataTime = c.DataTime, Station = c.Station, Datas = c.Datas.Where(x => x.Factor.Equals("Temperature")) }).ToList();
并且试过用ElemMatch去过滤嵌套子集合也不好使,查询出来的子集时全部:
FilterDefinitionBuilder<RealTimeData> builder = Builders<RealTimeData>.Filter; var filter =builder.Lte(x => x.DataTime, DateTime.Parse("2021-03-29 17:59:00")) & builder.Gte(x => x.DataTime, DateTime.Parse("2021-03-29 17:00:00")) & builder.ElemMatch(x => x.Datas, y => y.Factor.Equals("Temperature")); var list1 = collection.Find(filter).ToList();
上面代码都是经过脱敏处理的,但是大概样子是这样,求高人指点。
1.datetime 字段 加个索引,先试试看
2.datas 数据有点大,量不可控。考虑拆分出去。先查station,处理业务时 再查 factor
是有索引的,共两个索引,{datatime -1,Datas.Factor 1}另一个是{station 1,datatime -1,Datas.Factor 1},目前最快的方式是用游标去查询,并且里面也用project选择查询部分字段,这样最快的情况下,查询结果3W条,里面datas中大概20多条,耗时50秒。
设计有问题,把datas分开,单独存到一个document,带上一个station的id
现在是这么尝试的,但是似乎没啥效果,查询一小时时的数据,上面取出了3w条,datas要取3w*12条,主子集合取完,大概耗时100秒左右。
@Yu2: 其实查询速度挺快的,慢就慢在最后面那个tolist,你可以打个断点调试一下
@不知道风往哪儿吹: 是这样,取数据的过程很慢,而且也很耗内存,这就有点坑了。
@Yu2: 你把这么多数据放到内存,肯定慢,你先把要处理的数据都处理好,然后得到你需要的数据再放到内存,总之就是不要把查询的数据一下全放到内存