优化旋转和填充

时间:2019-03-11 09:10:50

标签: python pandas apache-spark pyspark

他们给了我一张表格,其中存储着模式为[TimeStamp, SensorKey, SensorValue]的传感器读数。

TimeStamp             Id           Value
2019-01-01 00:00:47   1            66.6
2019-01-01 00:00:47   2            0.66
2019-01-01 00:00:57   1            66.7
2019-01-01 00:00:57   2            0.68
2019-01-01 00:00:57   3            166.6
2019-01-01 00:01:07   3            146.6

请注意,它仅以有限的精度和采样率存储对传感器读数的更改,并且如果不更改,则在最后一次更改后每小时每小时重复一次该值。

当传感器Z值通过此条件时,它们查询传感器A(以及B,C,D ...)的平均值。他们想要使用Python和Spark。

因此,为了比较不同传感器的值,我获得了这些传感器键的行,并将结果旋转到模式[TimeStamp,ValueOfA,...,Z值]。

df1 = df0.groupBy("TS").pivot("Id", listOfIds).agg(F.last("Value"))

TimeStamp             Sensor1      Sensor2     Sensor3
2019-01-01 00:00:47   66.6         0.66        Null
2019-01-01 00:00:57   66.7         0.68        166.6
2019-01-01 00:01:07   Null         Null        146.6

然后我填补空白(始终,如果我没有较旧的数据来填补前几行,我将其丢弃)。

window1hour = Window.orderBy('TS').rowsBetween(-360, 0)
# 360 = 1 hour / 0.1 Hz sampling rate.
df2 = df1
for sid in sensorIds:
    df2 = df2\
        .withColumn(sid, F.last(F.column(sid), ignorenulls=True).over(window1hour))\
        .filter(F.column(sid).isNotNull())

现在,逐列进行比较是不重要的。

但是,与用pandas做同样的事相比,它要慢得多,以至于感觉我做错了。至少对于小型查询。

发生了什么事? 当查询很大时会发生什么?

关于小型和大型:我有数千种不同的传感器,每年大约有十亿条记录。因此,数据肯定适合一台服务器,而不适合RAM。实际上,他们将仅从一台服务器开始存储数据,也许在第二个Spark实例(具有多处理器和大量内存)的服务器上开始,并且希望如果看到回报,他们将投资更多的硬件。他们将开始每天进行小的查询,并且希望它们很快。但是后来他们将要在数年内进行查询,并且决不能爆炸。

想法/疑问:预处理是否在单个线程中完成?我应该自己动手并行化,还是让Spark处理它?我是否应该在很多天跨度的查询中打破跨年查询(但那为什么我要完全使用Spark)?我是否可以解决熊猫中的小查询和Spark中的大查询(我可以预先设置阈值)吗?

我还可以应用其他哪些改进?

1 个答案:

答案 0 :(得分:2)

在“火花”以外的其他工具中,“小”数据变得更快的情况并不少见。 Spark的并行功能具有相当大的开销(当然,与旧的map-reduce范例相比,这些开销很小)。

闪耀之处在于它可以通过添加服务器来线性缩放“大”数据。在这一点上,开销变得值得了,因为它将自动在所有可用的执行程序之间分解工作。

我相信,即使只是为了简单起见,让spark处理并行化也是理想的。是否在另一个框架中实现“小”查询完全取决于您是否要维护两个代码路径,以及客户是否对它们的速度感到满意。