为什么具有更新输出模式的流查询会打印出所有行?

时间:2018-07-27 07:25:44

标签: apache-spark spark-structured-streaming

我的目录中有三个文本文件:

a.txt

A B
C D
A E
F

b.txt

A B
C D
A E

c.txt

A B
C D
A E
G

我使用以下流查询:

val schema = new StructType().add("value", "string")
val lines = spark
  .readStream
  .schema(schema)
  .option("maxFilesPerTrigger", 1)
  .text(...)
  .as[String]

val wordCounts = lines.flatMap(_.split("\\s+")).groupBy("value").count()

val query = wordCounts.writeStream
  .queryName("t")
  .outputMode("update") // <-- output mode: update
  .format("memory")
  .start()

while (true) {
  spark.sql("select * from t").show(truncate = false)
  println(new Date())
  Thread.sleep(1000)
}

查询始终输出以下结果:

+-----+-----+
|value|count|
+-----+-----+
|A    |2    |
|B    |1    |
|C    |1    |
|D    |1    |
|E    |1    |
|A    |4    |
|B    |2    |
|C    |2    |
|D    |2    |
|E    |2    |
|G    |1    |
|A    |6    |
|B    |3    |
|C    |3    |
|D    |3    |
|E    |3    |
|F    |1    |
+-----+-----+

似乎每个文件的结果都附加到输出结果中(如Append输出模式),我不确定我是否了解update模式的含义。 update输出模式如何工作?

1 个答案:

答案 0 :(得分:3)

追加模式下,仅将自上次触发以来添加到结果表中的新行输出到接收器。 仅对那些永远不会更改添加到结果表中的行的查询支持。因此,此模式保证每行仅输出一次。

更新模式下,仅结果表中自上次触发以来已更新的行将被输出到接收器。

为了更好地理解这些模式,我将输出格式更改为控制台,并修改了以更新模式执行的数据,结果如下:

a.txt
A B
C D
A E
F X
Y Z

b.txt
A B
C D
A E

c.txt
A B
C D
A E
G


scala> val query = wordCounts.writeStream.queryName("t").outputMode("update").format("console").start()
query: org.apache.spark.sql.streaming.StreamingQuery = org.apache.spark.sql.execution.streaming.StreamingQueryWrapper@1985f8e3

scala> -------------------------------------------
Batch: 0
-------------------------------------------
+-----+-----+
|value|count|
+-----+-----+
|    F|    1|
|    E|    1|
|    B|    1|
|    Y|    1|
|    D|    1|
|    C|    1|
|    Z|    1|
|    A|    2|
|    X|    1|
+-----+-----+

-------------------------------------------
Batch: 1
-------------------------------------------
+-----+-----+
|value|count|
+-----+-----+
|    E|    2|
|    B|    2|
|    D|    2|
|    C|    2|
|    A|    4|
+-----+-----+

-------------------------------------------
Batch: 2
-------------------------------------------
+-----+-----+
|value|count|
+-----+-----+
|    E|    3|
|    B|    3|
|    D|    3|
|    C|    3|
|    A|    6|
|    G|    1|
+-----+-----+

您可以看到,每个批次的控制台中仅显示自上次触发以来已更新的行。 (例如:X,Y,Z计数不会在批次1和2中显示,因为它们没有更新。)

在您的情况下,您正在将数据写入内存。由于您没有逐出每个批次的内存,因此在查询时也会检索以前的批次数据。希望这些模式现在就清楚了。