编写带有一长串标记过滤器的流量查询的最佳方式是什么



假设我有一个记录大量数据的流入测量。每个点都用一个唯一的id进行标记,该id标识数据源和类型。

进入该测量的条目示例:

data,id=source1,type=temperature value=25
data,id=source1,type=battery value=80
data,id=source2,type=temperature value=22
data,id=source2,type=battery value=86

除此之外,我还有一个SQL数据库,其中包含有关每个源的详细信息。像位置、当前状态等。我想根据其他数据库中的信息过滤InfluxDB中的数据。因此,我获取了一个与我的过滤器匹配的id列表,然后可以用于通量查询。此列表的长度可以是数千。

我目前基于此列表进行过滤的解决方案是使用contains((函数:

from(bucket: "my-bucket")
|> range(start: -24h, stop: now())
|> filter(fn: (r) => 
r._measurement == "data" and 
r.type == "temperature" and 
contains(value: r.id, set: ["source1","source2", ...])
)
|> ...

这个查询变得非常慢,大约有1000个id,查询大约需要30秒才能完成。如果我删除contains过滤器并同时查看所有源,那么查询大约需要1秒。

有没有更好的方法可以做到这一点,而不用用我可能想过滤的所有东西来标记每个点。

InfluxDB在查询中有一个下推的概念。根据文件:

Pushdown是将数据操作推送到底层数据源而不是对内存中的数据进行操作的函数或函数组合。使用下推启动查询以提高查询性能。一旦非下推函数运行,Flux就会将数据拉入内存,并在内存中运行所有后续操作。

在您的情况下,示例中的过滤器不会向下推送到数据源,而是很可能在内存中进行处理,因为处理过滤器是内联的。而包含并不是最有效的方法

试试这个:

from(bucket: "my-bucket")
|> range(start: -24h, stop: now())
|> filter(fn: (r) => r.id =~ /^(source1|source2)$/)
|> filter(fn: (r) => 
r._measurement == "data" and 
r.type == "temperature"))
|> ...

在这里,我们使用regex通过值列表进行筛选。它应该比包含的性能更好。或者,您可以使用(r.id = "source1" or r.id = "source2")构建一个筛选器。

有关查询优化的更多信息,请阅读此处。

最新更新