最近做交易策略的回测,采用的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 $l2.单次查询的数量
另外一个简单有效的办法就是,合理调整查询的 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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。