2

最近做交易策略的回测,采用的influxdb3存储行情数据,使用过程中遇到的几个小问题,做如下记录总结。


1.查询条件的精确

一开始,我采用的查询语句比较简单,仅指定查询时间起点,这在初期并没有出现问题。但是随着写入 measurement 的数据量累积变大后,遇到了查询错误。查询语句及报错信息如下:

// 查询语句
"SELECT * FROM trade WHERE time > $t ORDER BY time ASC LIMIT 1000"

// 错误信息
 Internal desc = Error while planning query: External error: Query would exceed file limit of 432 parquet files. Please specify a smaller time range for your query. You can increase the file limit with the `--query-file-limit` option in the serve command, however, query performance will be slower and the server may get OOM killed or become unstable as a result

如上,错误的直接原因是查询的时间范围太大,导致需要访问的 Parquet 文件数量超过了当前的文件限制(432)。InfluxDB 的服务器在启动时可以通过 --query-file-limit 参数设置这个限制,默认可能是432。当查询涉及的文件数超过这个值,就会报错。

针对这个错误,当然可以选择增大查询文件限制,如果确实需要一次性查询大时间范围的数据,可以调整服务器的--query-file-limit参数,增大这个值。但是一般来说,这不是正确的解决办法。优化自己的代码才是正道。

首先应该从优化查询语句入手,让查询的时间范围变得更短更精确。因为仅指定查询的起始时间点,而不指定截止时间点,就相当于默认当前时间便是截止时间点。假如你的查询起点是100天前,那么influxdb会扫描近100天的所有分区(可能成百上千个),每个分区可能包含多个 Parquet 文件,最终导致扫描的文件总数超过 432 的限制。即便不超出 432 的限制,也是对性能的严重浪费。因此可以根据实际情况,精确查询的时间范围。如下:

SELECT * FROM depthupdate 
    WHERE time > $t1 
        AND time < $t2 
    ORDER BY time ASC LIMIT 1000

至于优化后的效果,也是非常明显的,不止是避免 432 限制的报错,对于CPU的占用,也是明显减少,从57.8%到6.3%,如下:

// 优化前
 PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND    
  67567 ubuntu    20   0 1312096  75432  16256 S 102.0   1.9   5:17.70 backtest                                  
   1655 ubuntu    20   0 6755148   1.3g  66816 S  57.8  33.3 848:36.98 influxdb3                                 
  48513 ubuntu    20   0 1243808  24244  14208 S   3.3   0.6  38:39.51 downloader   

// 优化后
 PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                              
 105350 ubuntu    20   0 1246632  46020  15744 S  91.8   1.1   0:06.10 backtest                                                             
   1655 ubuntu    20   0 7543704   1.1g  32256 S   6.3  28.7   1318:20 influxdb3                                                            
  48513 ubuntu    20   0 1243808  17260   7552 S   0.7   0.4 108:14.46 downloader 

其次,还可以通过添加标签过滤,来优化查询速度。添加标签过滤条件可利用 InfluxDB 的 TSI 索引,仅扫描包含该标签的分区,大幅减少文件数。标签过滤会让 InfluxDB 跳过不包含该标签的分区(即使这些分区在时间范围内)。如下:

// 假设只查询 BTCUSDT 交易对的订单
SELECT * FROM "trade" 
WHERE "symbol" = 'BTCUSDT'  -- 标签过滤(TSI 索引加速)
  AND time > now() - 7d 
  AND time < now() 
ORDER BY time ASC 
LIMIT $l

2.单次查询的数量

另外一个简单有效的办法就是,合理调整查询的 Limit。因为 inlfluxDB 的顺序读取效率极高,因此合理的提高 Limit 也是非常有效的。

3.influxdb 内存暴涨至机器崩溃

某次鲁莽更新后,发现 influxdb 内存占用暴涨,导致机器崩溃。重启机器后一切正常,然后重启 influxdb,发现 influxdb 的内存占用直线上升,直至机器再次崩溃。
排查发现,是因为,之前的写入数据,都是微秒级的,调用 influxdb 接口时也指定了是微秒级数据。但是本次更新后,接口信息没变,但是传入参数是毫秒。导致了整个 table 的时间跨度非常大(1970~2025)。
基于 influxdb 本身的预加载和分片机制,导致其启动后,因为时间跨度的巨大而加载的 Parquet 也是巨大的,因此会耗尽内存最终崩溃。

4.从3.1升级至3.4,端口号变了

3.1 版本安装后,默认端口号是 8181,升级至 3.4 后,默认端口号是 8182。但是 influxdb 的客户端仍然访问的是 8181,因此就会报错:

error sending request for url (http://127.0.0.1:8181/api/v3/configure/database?format=pretty&show_deleted=false): error trying to connect: tcp connect error: Connection refused (os error 111)

服务已经启动且持续写入数据,因此不打算修改服务的端口号,但是没找到客户端的端口号配置文件,因此暂时在命令中指定 --host,例如:

influxdb3 show databases --host http://localhost:8182

soroqer
199 声望14 粉丝

引用和评论

0 条评论