大佬们,请教一下数据读取 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
iamtuzi3333
V2EX    程序员

大佬们,请教一下数据读取

  •  
  •   iamtuzi3333 284 天前 2432 次点击
    这是一个创建于 284 天前的主题,其中的信息可能已经有所发展或是发生改变。
    小弟负责是后端内容的编写,现在系统有一批传感器,数据格式都是 json ,每个传感器每秒都有数据发送过来。我接收,然后写入文件,每天一个.json ,例如:传感器编号-日期-文件,这样的格式。文件中每行都是{}的数据,里面有时间戳,data ,例如{"time":12346574,"data":[1,2,3,4,5]},每一行都是这样的形式。文件夹目录有分层,每天都有一个日期对应的目录,里面就是当天的数据文件。数据同时存入到数据库 Mongo 中,单个节点,建了 time 字段的索引。现在查询历史数据量多的话感觉速度还是有点慢,依靠 time 字段找出时间范围的数据,取出每条数据的 data 元素;现在小弟想数据库只存储当前 3 天的数据,就是额外写一个脚本定时删除三天以前的数据,然后历史数据改为读取对应文件及日期的文件数据,这样读取历史数据是否可行,速度是否更快呢,后端用的 node ,他读取数据量量一大就容易内存栈,这个 data 字段元素有 200 个浮点数,一天能存 86400*200 多个数字,所以读取历史数据有时候读的时间范围大就容易崩,想请教大佬们怎么处理好一点。
    26 条回复    2025-01-02 09:06:52 +08:00
    skallz
        1
    skallz  
       284 天前
    如果查询范围不大的话,可以考虑直接让前端拿对应文件的内容前端处理,让客户端分担服务端的性能压力,哈哈哈哈,前提是你的文件服务器和业务服务器不是同一个服务器,比如用的云服务商 oss 之类的
    chihiro2014
        2
    chihiro2014  
       284 天前
    为什么感觉应该是使用 influxdb 之类的产品,而不是 mongo
    xiaofsu
        3
    xiaofsu  
       284 天前
    最好的办法就是换个时序数据库。
    daxin945
        4
    daxin945  
       284 天前
    如果是我的话可能会用 clickhouse 替换 mongo
    MoYi123
        5
    MoYi123  
       284 天前
    没必要, 数据库一般会用一些压缩算法, 肯定比你支持存 json 文件要省的.
    数据库里用 partition table, 按日期分
    内存溢出肯定是你代码有错, 86400*200 个 float 应该还不到 100MB.
    timethinker
        6
    timethinker  
       284 天前
    mongodb 从 5.0 开始支持时间序列( Time Series ),可以提高查询速度。

    https://www.mongodb.com/docs/manual/core/timeseries/timeseries-procedures/
    sagaxu
        7
    sagaxu  
       284 天前
    数据总量是多少,每次查询返回多少,有点儿慢是多慢,查询是怎么写的,这些都没讲清楚,不大好分析。
    Oldletter
        8
    Oldletter  
       284 天前
    MongoDB 支持 TTL 索引,允许自动删除超过指定时间的数据。你可以为 time 字段创建一个 TTL 索引来确保数据库中只保留 3 天的数据,这样就不需要手动写脚本来删除过期数据。

    你的数据感觉不是特别大,所以建议你看看代码问题吧
    iamtuzi3333
        9
    iamtuzi3333  
    OP
       284 天前
    @skallz 范围也大,会查询去年某一个月的所有数据,前端处理不太现实,现在文件跟业务都在一个服务器。
    @chihiro2014 我之前看过这个,但是他对 json 格式数据不太友好,部署相对麻烦。
    @xiaofsu 看了部分时序数据库,发现部分接口、迁移、数据格式不太方便。
    @daxin945 我查查这个数据库看看效果。
    iamtuzi3333
        10
    iamtuzi3333  
    OP
       284 天前
    @MoYi123 内存溢出是 node 的问题好像,我试过查询去年某一段时间的数据,他就查询内存栈溢出了。
    @sagaxu 数据总量很多,每天 86400 条 json 存入,每次查询返回不定期,就是得根据前端传回的时间范围作为查询条件,有时候会查询去年某一段时间的数据,慢的时候主要是等待很久,数据库的每个集合的 timestamp 字段有做索引。查询代码如下:
    // 获取 MongoDB 原生数据库连接
    const db = mongoose.connection.db;
    // 获取指定的集合
    const collection = db.collection(collectionName);
    // 构建查询条件
    const query = {};
    const timestampInt = parseInt(timestamp, 10);
    query.timestamp = timestampInt;
    // 查询数据
    const result = await collection.find(query).toArray();
    if (result.length <= 0) {
    ctx.status = 200;
    ctx.body = { message: 'no data', data: [] };
    return;
    }

    @Oldletter 代码相对来说比较简单,就是传入集合名字,时间范围,就去对应的结合查询,查询代码如上,后端用的 node ,koa 框架,但是我发现 Mongo 的数据迁移不太方便,比如说我要把 a 服务器的某一个库的所有数据转移到 b 服务器的 Mongo 实例中,就不太方便了。
    Nitsuya
        11
    Nitsuya  
       284 天前
    @daxin945 #4 +1
    sagaxu
        12
    sagaxu  
       284 天前
    前端查一个月的数据干嘛用?浏览器根本无法展示。显然要做好聚合,缩小数据规模。
    aloxaf
        13
    aloxaf  
       284 天前   1
    没用过 MongoDB ,不过这类时间序列数据查询的优化方向都是差不多的:
    1. 提前按天、按小时聚合数据,根据查询范围来调整返回数据的精度。就像楼上说的,一个月的数据得上百万条了,前端要这么多数据干嘛。
    2. 原始数据可以存的时候就按小时打包来存,没必要每秒生成一条记录。
    3. 你这数据量也不大,但不知道 MongoDB 存这些数据效率如何,如果太占空间可能要考虑对旧数据降采样(你真的需要查询三年前某分钟内每秒的数据?)或者转冷存储。

    不过还是推荐直接用数序数据库,不仅速度更快还节省空间,而且「优化花费的时间」未必比「迁移花费的时间」更少,除了 influxdb 外也可以看看 timescaledb ,对于有 sql 经验的人来说迁移真的方便)
    iamtuzi3333
        14
    iamtuzi3333  
    OP
       284 天前
    @sagaxu 查询画图展示,长时间的我会额外查询宿友再处理,比如每十分钟提取一个最大值,汇聚所有的值返回。但是归根到底我还是要查询这些时间范围的数据。
    @aloxaf 前端查询数据主要是展示,会有额外的需求,不过我还是要单独查询出这些范围的数据做进一步的加工。原始数据是传感器就固定每秒会有数据,传感器一多,每小时打包就不方便了,有时需要上半段,有时候需要下半段,每秒是最好的处理方法。数据会查询很久之前的,需要保持。时序数据库我还在找,发现挺多不怎么合适,总有一两项让我退步
    nivalxer
        15
    nivalxer  
       284 天前
    场景比较类似,只不过我们这边传感器数据没有到每秒,一般大概 10 几秒到几分钟不等。
    目前也是 Mongodb 的方案,按每个站点(一个站会有多个参数)一张表方式存储,每个小时会抽一条数据放小时表,统计报表再根据公司配置进行公司表级的存储。
    Mongodb 需要考虑查出来的文档返回不能超过 16M ,虽然有一些配置可以绕过限制。目前感觉在数据量比较多,也根据查询条件(时间等)加了索引情况下,响应速度一般。
    如果数据比较频繁并且需要偶尔查出来比较多的历史数据(多天、月、季度)还是看看其他的方案,目前我也想看看有没有除 MongoDb 外的其他更好的方案。
    hd10180
        16
    hd10180  
       284 天前
    虽然我很菜,但我也做过类似的数据处理。
    我的看法是要分析的数据不要存成数组,后期可能不方便做查询,data 的每个数值应该有个属性名。
    假设[26, 80, ..]代表的是 [温度, 湿度, ...] 转成 temp: value, hum: value 的方式存储。可能你的情况跟我的不太一样,就当我没说。
    另外每个传感器应该有 uuid 的吧,索引做成 uuid+time 不知道会不会好些?还可以考虑写个额外的程序对数据做分析,比如做小时维度的数据统计、月维度的统计等。
    securityCoding
        17
    securityCoding  
       284 天前
    时序数据库干的活不要硬来
    yyt6801
        18
    yyt6801  
       284 天前
    楼上都提到的时序数据库就是为了解决这种问题, 首先你要知道 每秒的那个 data:[]里面都代表什么东西;知道结构其他都好办了, 剩下的交给时序数据库解决
    sagaxu
        19
    sagaxu  
       284 天前   1
    @iamtuzi3333 “比如每十分钟提取一个最大值”,这个事情可以提前做好。我之前做过一个数据结构类似的项目,有分钟汇总,小时汇总,天汇总,都是提前生成缓存好,当日数据还会存一份在内存里加速访问。一般查询都有个特点,时间段跨度越大,越不关心局部数据,缓存好的汇总表能极大提高查询速度。

    一次查大量数据,只能在后台定时任务里跑,不能由前端触发查询,否则任何数据库都无法满足。数据量量一大,即使 nodejs 直接读文件解析,不经过 db ,也会消耗很大资源。
    1Z3KYa0qBLvei98o
        20
    1Z3KYa0qBLvei98o  
       284 天前 via iPhone
    @skallz 我一般就是这么做的
    kivmi
        21
    kivmi  
       284 天前
    从大数据处理基本都是 map-reduce ,所以,这么直接查询原始数据,总感觉有些不妥
    iamtuzi3333
        22
    iamtuzi3333  
    OP
       283 天前
    @nivalxer 我是每个传感器一个表,返回的文档长度不超过 16M 吗,有更好的方案可以分享一下。
    @hd10180 他格式没有这么多,就是固定的 data 数组,要么 50,100,200 ,是根据采样率来定的。传感器也没有 uuid 全靠自己编。
    @yyt6801 data 数组就是 50 或者 100 或者 200 个浮点数,每秒的数据都是这样。
    @sagaxu 是的,我现在只统计了每秒的最大值,最小值,平均值,读取起来还不算太费劲。正常来说我们只关注十分钟这个节点,还有每分钟数据,这个都还算好用处理。文件确实,主要是读取文件比较麻烦,文件目录不固定,没有很好的索引方式。
    @kivmi 是的,但是我们的数据也不算大,就是多,频繁,每秒都有,直接查询原始数据出来也是为了做进一步处理,比如取出每一分钟的最大值,最小值,均值,方差这一些。
    nivalxer
        23
    nivalxer  
       283 天前
    我们这边行业比较特殊,对接 PLC 走场站这块,虽然 PLC 站控那边数据是实时的,我们采集远传还是以间隔来走的,所以数据量不会太多,在 10 秒频率下,按天走也不会超过 16M 。这个 16M 是输出文档大小,如果采用分页查询等,输出文档不超过 16M 也没啥问题。
    数据库我们暂时还是 mongodb 还没改,计划后面改,还没测试其他方案。
    我们行业场景,其实客户不会关注每秒的数据情况,所以大部分时间客户查的小时表(每小时一条取样)和统计表(小时、日、月)这两种,压力就还好。少量在出报警、统计到处等场景才会查完整历史数据。
    可以按客户场景来处理。如果客户有每条数据必须存和频繁的查询需求,在不过多改动现有技术架构情况下,可能看看其他数据库比较合适。
    fishman231
        24
    fishman231  
       283 天前
    MongoDB 也是有时序集合,可以使用 TTL 索引自动删除过期文件.另外时序集合可压缩数据,这样是否可以所有数据都存数据库呢
    pangzipp
        25
    pangzipp  
       283 天前
    mongodb 本身有数据压缩
    你能够实现 3 天以前数据读本地文件文件, 那也可以在 mongodb 里分表。

    可以评估下计划投入的资源,成本多少?
    用自己熟悉的技术栈
    iamtuzi3333
        26
    iamtuzi3333  
    OP
       281 天前
    @nivalxer 挺好,后者历史数据我们很像,不过我就是还有一个实时数据的波形展示。
    @fishman231 我查询看看。
    @pangzipp 目前还没有实现三天以前读取本地文件,就是想这么做,看到一个方案就是只存储最近几天的数据,然后历史数据都存储到文件,查询历史数据通过读文件的形式去完成。MongoDB 分表我还不熟悉;技术栈都是啥好用简单方便就上啥了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1015 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 22:54 PVG 06:54 LAX 15:54 JFK 18:54
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86