Почему использование кэша в потоковых наборах данных не удается с помощью " AnalysisException: запросы с потоковыми источниками должны выполняться с помощью writeStream.start()"?
SparkSession
.builder
.master("local[*]")
.config("spark.sql.warehouse.dir", "C:/tmp/spark")
.config("spark.sql.streaming.checkpointLocation", "C:/tmp/spark/spark-checkpoint")
.appName("my-test")
.getOrCreate
.readStream
.schema(schema)
.json("src/test/data")
.cache
.writeStream
.start
.awaitTermination
при выполнении этого образца в spark 2.1.0 я получил ошибку.
Без .cache
опция работала по назначению, но с Я:
исключение в потоке" main " org.апаш.искра.язык SQL.AnalysisException: запросы с потоковыми источниками должны выполняться с помощью writeStream.начать();; FileSource[src / тест / данные] на org.apache.spark.sql.catalyst.analysis.UnsupportedOperationChecker$.org$apache$spark$sql$catalyst$analysis$UnsupportedOperationChecker$$throwError(UnsupportedOperationChecker.scala:196) в орг.апаш.искра.язык SQL.катализатор.анализ.UnsupportedOperationChecker$$anonfun$checkForBatch$1.применить(UnsupportedOperationChecker.scala: 35) в орг.апаш.искра.язык SQL.катализатор.анализ.UnsupportedOperationChecker$$anonfun$checkForBatch$1.применить(UnsupportedOperationChecker.scala: 33) на орг.апаш.искра.язык SQL.катализатор.деревья.объект TreeNode.foreachUp(узлов дерева.scala: 128) в орг.апаш.искра.язык SQL.катализатор.анализ.UnsupportedOperationChecker$.checkForBatch (UnsupportedOperationChecker.scala: 33) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.assertSupported (QueryExecution.scala: 58) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.withCachedData$lzycompute (QueryExecution.scala: 69) на орг.апаш.искра.язык SQL.исполнение.QueryExecution.withCachedData (QueryExecution.scala: 67) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.optimizedPlan$lzycompute (QueryExecution.scala: 73) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.optimizedPlan (QueryExecution.scala: 73) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.sparkPlan$lzycompute (QueryExecution.scala: 79) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.sparkPlan (QueryExecution.scala: 75) на орг.апаш.искра.язык SQL.исполнение.QueryExecution.executedPlan$lzycompute (QueryExecution.scala: 84) в орг.апаш.искра.язык SQL.исполнение.QueryExecution.executedPlan (QueryExecution.scala: 84) в орг.апаш.искра.язык SQL.исполнение.CacheManager$$anonfun$cacheQuery$1.применить(CacheManager.scala: 102) в орг.апаш.искра.язык SQL.исполнение.CacheManager.writeLock(CacheManager.scala: 65) в орг.апаш.искра.язык SQL.исполнение.CacheManager.cacheQuery (CacheManager.scala: 89) на орг.апаш.искра.язык SQL.Набор данных.сохраняются(набора данных.scala: 2479) в орг.апаш.искра.язык SQL.Набор данных.кэш(набор данных.scala: 2489) в орг.меня.App$.main (App.scala: 23) в орг.меня.App.main (App.scala)
есть идеи?
1 ответов
ваш (очень интересный) случай сводится к следующей строке (которую вы можете выполнить в spark-shell
):
scala> :type spark
org.apache.spark.sql.SparkSession
scala> spark.readStream.text("files").cache
org.apache.spark.sql.AnalysisException: Queries with streaming sources must be executed with writeStream.start();;
FileSource[files]
at org.apache.spark.sql.catalyst.analysis.UnsupportedOperationChecker$.org$apache$spark$sql$catalyst$analysis$UnsupportedOperationChecker$$throwError(UnsupportedOperationChecker.scala:297)
at org.apache.spark.sql.catalyst.analysis.UnsupportedOperationChecker$$anonfun$checkForBatch.apply(UnsupportedOperationChecker.scala:36)
at org.apache.spark.sql.catalyst.analysis.UnsupportedOperationChecker$$anonfun$checkForBatch.apply(UnsupportedOperationChecker.scala:34)
at org.apache.spark.sql.catalyst.trees.TreeNode.foreachUp(TreeNode.scala:127)
at org.apache.spark.sql.catalyst.analysis.UnsupportedOperationChecker$.checkForBatch(UnsupportedOperationChecker.scala:34)
at org.apache.spark.sql.execution.QueryExecution.assertSupported(QueryExecution.scala:63)
at org.apache.spark.sql.execution.QueryExecution.withCachedData$lzycompute(QueryExecution.scala:74)
at org.apache.spark.sql.execution.QueryExecution.withCachedData(QueryExecution.scala:72)
at org.apache.spark.sql.execution.QueryExecution.optimizedPlan$lzycompute(QueryExecution.scala:78)
at org.apache.spark.sql.execution.QueryExecution.optimizedPlan(QueryExecution.scala:78)
at org.apache.spark.sql.execution.QueryExecution.sparkPlan$lzycompute(QueryExecution.scala:84)
at org.apache.spark.sql.execution.QueryExecution.sparkPlan(QueryExecution.scala:80)
at org.apache.spark.sql.execution.QueryExecution.executedPlan$lzycompute(QueryExecution.scala:89)
at org.apache.spark.sql.execution.QueryExecution.executedPlan(QueryExecution.scala:89)
at org.apache.spark.sql.execution.CacheManager$$anonfun$cacheQuery.apply(CacheManager.scala:104)
at org.apache.spark.sql.execution.CacheManager.writeLock(CacheManager.scala:68)
at org.apache.spark.sql.execution.CacheManager.cacheQuery(CacheManager.scala:92)
at org.apache.spark.sql.Dataset.persist(Dataset.scala:2603)
at org.apache.spark.sql.Dataset.cache(Dataset.scala:2613)
... 48 elided
причина этого оказалась довольно простой в объяснении (нет каламбура для Искры SQL explain
предназначен).
spark.readStream.text("files")
создает так называемый потоковая передача данных.
scala> val files = spark.readStream.text("files")
files: org.apache.spark.sql.DataFrame = [value: string]
scala> files.isStreaming
res2: Boolean = true
потоковые наборы данных являются основой Spark SQL в Структурированная Потоковая Передача.
как вы, возможно, читали в Structured Трансляции -Пример:
а затем начать потоковое вычисление с помощью
start()
.
цитирование scaladoc из Datastreamwriter's старт:
start (): StreamingQuery запускает выполнение потокового запроса, который будет постоянно выводить результаты на заданный путь по мере поступления новых данных.
Итак, вы должны использовать start
(или foreach
) чтобы начать выполнение потокового запроса. Ты уже знал это.
но...есть Неподдерживаемые Операции в структурированной потоковой передачи:
кроме того, есть некоторые методы набора данных, которые не будут работать с потоковыми наборами данных. Это действия, которые немедленно запускают запросы и возвращают результаты, что не имеет смысла в потоковом наборе данных.
если вы попробуете любую из этих операций, вы увидите AnalysisException как "операция XYZ не поддерживается потоковыми фреймами данных/наборами данных".
знакомое, не так ли?
cache
и не в списке неподдерживаемых операций, но это потому, что он просто был упущен (я сообщил Искра-20927 исправить).
cache
должен был быть в списке, как это тут выполнить запрос до получения запроса зарегистрировано в Искра CacheManager в SQL.
давайте углубимся в глубины Spark SQL...задержать дыхание...
cache
is persist
пока persist
запрашивает текущий CacheManager для кэширования запроса:
sparkSession.sharedState.cacheManager.cacheQuery(this)
при кэшировании запроса CacheManager
тут выполнить:
sparkSession.sessionState.executePlan(planToCache).executedPlan
что мы знаю не допускается, так как это start
(или foreach
), чтобы сделать так.
проблема решена!