IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    InfluxDB 诡异的时间窗口对齐

    obaby发表于 2025-05-27 01:27:33
    love 0

    之前的项目,将部分数据迁移到了InfluxDB v2 数据库。但是,在查询数据的时候发生了一件很诡异的事情,就是使用不同的时间间隔,返回的数据却完全不一样。

    查询代码如下:

    def query_data_with_5min_sampling(device_id, start_time, end_time, interval='05m'):
        """
        查询指定设备在时间范围内的数据,支持不同的采样间隔
        :param device_id: 设备ID
        :param start_time: 开始时间
        :param end_time: 结束时间
        :param interval: 采样间隔,支持 '10s', '30s', '01m', '05m', '10m', '30m', '01h',默认为 '05m'
        :return: 采样后的数据列表
        """
        if interval is None or interval == '':
            interval = '05m'
        if 'm' not in interval and 's' not in interval:
            interval = f"0{interval}m" if int(interval) < 10 else f"{interval}m"
        # 验证时间范围,如果大于一天,强制使用5分钟采样
        if end_time - start_time > timedelta(days=1):
            interval = '05m'
        # 如果小于等于一天且没有指定间隔,使用1分钟采样
        elif interval == '5m' and end_time - start_time <= timedelta(days=1):
            interval = '01m'
    
        query = f"""
        from(bucket: "ts")
            |> range(start: {datetime_to_tz_time_string(datetime_to_utc_time(start_time))}, 
                    stop: {datetime_to_tz_time_string(datetime_to_utc_time(end_time))})
            |> filter(fn: (r) => r._measurement == "TSSourceData")
            |> filter(fn: (r) => r.device_id_string == "{device_id}")
            |> filter(fn: (r) => r._field =~ /^(temperature|humidity|health_level)$/)
            |> aggregateWindow(
                every: {interval},
                fn: mean,
                createEmpty: false
            )
            |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
        """
        
        tables = client.query_api().query(org="power", query=query)
        
        lines = []
        for table in tables:
            for record in table.records:
                lines.append(record.values)
        return lines

    数据支持: ’10s’, ’30s’, ’01m’, ’05m’, ’10m’, ’30m’, ’01h’,默认为 ’05m’

    然而,当使用 5 分钟为间隔查询的时候,返回的第一条数据时间竟然是 01 分,不是整点,查询代码:

    nt = current_time = get_rounded_time_before_time(8)
        # # print(nt)
        lines = query_data_with_5min_sampling('mddt6825050023_1', nt, datetime.now(), interval='5m')
        # print(lines)
        for data_point in lines:
            # print(data_point)   
            utc_time = data_point.get('_time')
            tz = pytz.timezone('Asia/Shanghai')
            local_time = utc_time.astimezone(tz)
            print(local_time.strftime('%Y-%m-%d %H:%M:%S'))

    执行结果:

    2025-05-27 01:01:00
    2025-05-27 01:06:00
    2025-05-27 01:11:00
    2025-05-27 01:16:00
    2025-05-27 01:21:00
    2025-05-27 01:26:00
    2025-05-27 01:31:00
    2025-05-27 01:36:00
    2025-05-27 01:41:00

    然而,当时间改成 15 分钟或者其他时间,就完全是按照整点以及时间间隔来的:

    lines = query_data_with_5min_sampling('mddt6825050023_1', nt, datetime.now(), interval='15m')

    执行结果:

    2025-05-27 01:15:00
    2025-05-27 01:30:00
    2025-05-27 01:45:00
    2025-05-27 02:00:00
    2025-05-27 02:15:00
    2025-05-27 02:30:00
    2025-05-27 02:45:00
    2025-05-27 03:00:00
    2025-05-27 03:15:00
    2025-05-27 03:30:00
    2025-05-27 03:45:00
    2025-05-27 04:00:00
    2025-05-27 04:15:00
    2025-05-27 04:30:00
    2025-05-27 04:45:00
    2025-05-27 05:00:00
    2025-05-27 05:15:00
    2025-05-27 05:30:00
    2025-05-27 05:45:00
    2025-05-27 06:00:00
    2025-05-27 06:15:00

    我勒个豆,这么神奇吗?对于这种错误其实猜测可能是返回数据的对齐粒度问题,但是在尝试了使用 offset 等各种参数之后,对于 5 分钟的数据还是返回了 01。直接崩溃,让 cursor 来回改,最后代码改的面目全非了依然没达到效果。只能回滚代码。

    这时候鬼使神差想到,这个参数既然是个字符串,那么传个 05m 呢?

    lines = query_data_with_5min_sampling('mddt6825050023_1', nt, datetime.now(), interval='05m')

    执行结果:

    2025-05-27 01:05:00
    2025-05-27 01:10:00
    2025-05-27 01:15:00
    2025-05-27 01:20:00
    2025-05-27 01:25:00
    2025-05-27 01:30:00
    2025-05-27 01:35:00
    2025-05-27 01:40:00
    2025-05-27 01:45:00
    2025-05-27 01:50:00
    2025-05-27 01:55:00
    2025-05-27 02:00:00
    2025-05-27 02:05:00
    2025-05-27 02:10:00
    2025-05-27 02:15:00
    2025-05-27 02:20:00

    竟然神奇的治愈了,这尼玛不得不说竟然这么神奇。所以最开始的代码其实是修复之后的代码,对于没有 0 开头的分钟进行填充。

    问了下 cursor,给出了下面的答复:

    这特性,真是服了,问题是 cursor,为什么不是你发现了告诉我?而是我发现了告诉你呢?

    果然是高级 quirk!

    The post InfluxDB 诡异的时间窗口对齐 appeared first on obaby@mars.



沪ICP备19023445号-2号
友情链接