DaZuiZui commented on issue #18532:
URL: https://github.com/apache/iotdb/issues/18532#issuecomment-5439245641

   ## 功能定义建议
   
   建议将 LTTB 定义为 Table Model 的内置表函数,参数约定与现有 M4 表函数保持一致。
   
   ### 1. SQL 语法
   
   ~~~sql
   SELECT *
   FROM LTTB(
     DATA    => TABLE(<query>),
     TIMECOL => DESCRIPTOR(<time_column>),
     N       => <target_count>
   );
   ~~~
   
   或:
   
   ~~~sql
   SELECT *
   FROM LTTB(
     DATA    => TABLE(<query>),
     TIMECOL => DESCRIPTOR(<time_column>),
     SIZE    => <window_size>,
     SLIDE   => <window_step>,
     ORIGIN  => <time_origin>
   );
   ~~~
   
   DATA 和 TIMECOL 为必选参数。两种执行模式必须二选一:
   
   * 目标点数模式:指定 N;N 与 SIZE、SLIDE、ORIGIN 互斥。
   * 窗口/桶模式:指定 SIZE;SLIDE 默认为 SIZE,ORIGIN 仅适用于时间窗口。
   
   ### 2. 参数含义
   
   * DATA:输入表,采用与 M4 相同的表参数语义。
   * TIMECOL:唯一时间列的 descriptor。该列必须为 TIMESTAMP 类型。函数应保证每个 partition 
内的数据按该列升序排列后再采样。
   * N:每个 partition、每个 participant column 的目标点数。必须为正整数,最小值为 3,因为 LTTB 
至少保留首点、尾点和一个中间点。
   * SIZE:桶/窗口大小。duration 值表示时间窗口,整数值表示按行数的窗口。
   * SLIDE:窗口步长,默认等于 SIZE;只有指定 SIZE 时才有效。
   * ORIGIN:时间窗口的起始基准;只适用于 duration 类型的 SIZE,不能用于计数窗口。
   
   不需要显式的 COL 参数。与 M4 一样,函数应自动识别 participant columns:除时间列和 partition columns 
外,所有支持的数值列分别独立处理。partition columns 原样保留,并定义相互独立的时间序列。
   
   ### 3. 支持的数据类型
   
   首版 participant columns 建议支持 INT32、INT64、FLOAT、DOUBLE;时间列必须为 
TIMESTAMP。partition columns 沿用 Table Model 分组已支持的数据类型。
   
   BOOLEAN、TEXT/STRING、二进制类型和复杂类型首版应拒绝,因为三角形面积计算需要有序的数值。后续如有明确的转换规则,再扩展其他类型。
   
   ### 4. 目标点数模式
   
   对每个 partition、每个 participant column:
   
   1. 构造按时间升序排列的 (timestamp, value) 点序列。
   2. 独立忽略该列 value 为 NULL 的行;NULL 不能当作 0,也不能参与平均值或三角形面积计算。
   3. 有效点数小于等于 N 时,直接返回全部有效点,不做插值。
   4. 有效点数大于 N 时,执行标准 LTTB,并准确返回 N 个点。
   5. 始终保留首个和最后一个有效点,输出按时间升序排列。
   
   每个 participant column 独立执行 LTTB,因此不同列可以选择不同的时间戳。目标点数模式的输出结构建议沿用 M4 的计数窗口:
   
   ~~~text
   window_index, <partition_columns>,
   <column_1>_time, <column_1>,
   <column_2>_time, <column_2>, ...
   ~~~
   
   目标点数模式下 window_index 固定为 0。各列按输出位置对齐;若由于 NULL 分布不同导致某列序列较短,则用 NULL 补齐。因此每个 
partition 最多输出 N 行;当所有 participant columns 的有效点数都大于 N 时,输出正好为 N 行。
   
   ### 5. 窗口/桶模式
   
   窗口构造应遵循 M4 的边界、开闭区间、时间 origin 和计数窗口规则。
   
   对每个桶、每个 participant column,使用以下 LTTB 三角形选择一个代表点:
   
   * A:此前已选中的点(锚点);
   * B:当前桶中的每个非 NULL 候选点;
   * C:下一个桶的平均点(对有效点计算平均时间和平均数值)。
   
   选择三角形面积最大的候选点;并用确定性的规则处理并列(例如选择时间最早的点)。空桶不产生该 participant column 
的点。需要明确首桶的锚点规则(建议使用 partition 中第一个有效点),以及没有下一个桶时的末桶规则(建议保留最后一个有效点)。
   
   输出结构与 M4 一致:
   
   * 时间窗口模式:
     ~~~text
     window_start, window_end, <partition_columns>,
     <column_1>_time, <column_1>,
     <column_2>_time, <column_2>, ...
     ~~~
   * 计数窗口模式:
     ~~~text
     window_index, <partition_columns>,
     <column_1>_time, <column_1>,
     <column_2>_time, <column_2>, ...
     ~~~
   
   当 SLIDE < SIZE 时,重叠窗口应遵循 M4 的 set semantics。LTTB 状态必须按 partition/window 
计算,不能依赖 fragment 的局部边界。
   
   ### 6. NULL 与边界行为
   
   * 每个 participant column 独立忽略 NULL。
   * 某 partition 的某列没有有效点时,该列输出 NULL。
   * 只有一个有效点时返回该点;只有两个有效点时返回两个点。虽然下采样要求 N >= 3,但短序列仍应按此规则返回。
   * 重复时间戳的处理应与 Table Model 其余部分保持一致,建议排序后保持稳定输入顺序,并在文档中明确。
   * 平均值和面积计算使用足够宽的中间类型(例如 DOUBLE),避免数值溢出。
   
   ### 7. 参数校验
   
   至少应拒绝以下情况:
   
   * N 和 SIZE 均未指定;
   * N 和 SIZE 同时指定;
   * N < 3,或 N 不是正整数;
   * N 与 SLIDE 或 ORIGIN 同时使用;
   * 未指定 SIZE 却指定 SLIDE 或 ORIGIN;
   * 计数窗口模式指定 ORIGIN;
   * TIMECOL 无效或不是 TIMESTAMP;
   * SIZE 或 SLIDE 为 0、负数或非法值;
   * participant column 使用不支持的数据类型。
   
   非法示例:
   
   ~~~sql
   SELECT *
   FROM LTTB(
     DATA => TABLE(sensor_data),
     TIMECOL => DESCRIPTOR(time),
     N => 500,
     SIZE => 1m
   );
   ~~~
   
   该调用应失败,因为 N 和 SIZE 选择了互斥的执行模式。
   
   ### 8. 执行与分布式语义
   
   函数应具有与 M4 一致的 set semantics。目标点数模式需要先知道每个 partition 的有效点总数才能确定桶边界,因此可能需要缓存 
partition 数据,并配合内存计费及必要的 spill 机制。窗口模式可通过保留前一个已选点以及当前、下一个桶来控制状态规模。
   
   LTTB 通常不可直接合并。在分布式执行中,必须先收集同一 partition 的全部数据并完成排序,再执行采样;不能简单拼接各 fragment 
的局部 LTTB 结果来得到全局正确结果。
   
   ### 9. 使用示例
   
   目标点数模式:
   
   ~~~sql
   SELECT *
   FROM LTTB(
     DATA => TABLE(
       SELECT time, temperature, pressure
       FROM sensor_data
       WHERE device_id = 'd1'
     ),
     TIMECOL => DESCRIPTOR(time),
     N => 500
   );
   ~~~
   
   计数窗口模式:
   
   ~~~sql
   SELECT *
   FROM LTTB(
     DATA => TABLE(SELECT time, temperature, pressure FROM sensor_data),
     TIMECOL => DESCRIPTOR(time),
     SIZE => 100,
     SLIDE => 100
   );
   ~~~
   
   时间窗口模式:
   
   ~~~sql
   SELECT *
   FROM LTTB(
     DATA => TABLE(SELECT time, temperature, pressure FROM sensor_data),
     TIMECOL => DESCRIPTOR(time),
     SIZE => 1m,
     SLIDE => 1m,
     ORIGIN => TIMESTAMP '2026-01-01 00:00:00'
   );
   ~~~
   
   ### 10. 建议测试
   
   建议覆盖:
   
   * 已知 LTTB 数据集的确定性结果;
   * 首点、尾点保留;
   * 输入有效点多于 N 时准确返回 N 个点;
   * 输入有效点不多于 N 时返回全部点;
   * 目标点数模式下 window_index 固定为 0;
   * 多个 participant columns 选择不同时间戳;
   * 不同 NULL 分布、空序列;
   * partition 输入;
   * 基于计数和基于时间的 SIZE;
   * 默认及显式 SLIDE;
   * ORIGIN 对齐;
   * 重叠窗口;
   * 非法参数组合和不支持的数据类型;
   * 单机与分布式执行结果一致。
   
   ### 11. 首版范围
   
   首版应优先保证确定性,并与 M4 的窗口语义保持一致,同时明确末桶、短序列和重叠窗口的处理规则。后续可根据实际用例扩展 participant 
数据类型或其他输出布局。


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to