- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
最近,我在为处理时间戳的 Java Spark 应用程序创建可靠的单元测试时遇到了很多麻烦。
具体来说,我很难说服自己,无论运行系统的时区如何,我正在测试的代码都会产生相同的结果。
以以下虚拟测试为起点:
public class TimestampsTest {
@Test
public void timestampsTest() {
SparkSession spark = SparkSessionBuilder.getTestSparkSession();
Timestamp timestamp1 = Timestamp.valueOf("2019-01-01 01:00:00");
println("Timestamp 1:");
println(timestamp1.toString());
println("Instant 1:");
println(timestamp1.toInstant().toString());
Timestamp timestamp2 = Timestamp.valueOf("2019-01-01 02:00:00");
println("Timestamp 2:");
println(timestamp2.toString());
println("Instant 2:");
println(timestamp2.toInstant().toString());
List<Row> rows = Arrays.asList(
RowFactory.create(timestamp1),
RowFactory.create(timestamp2)
);
StructType schema = DataTypes.createStructType(
Collections.singletonList(DataTypes.createStructField("timestamp", DataTypes.TimestampType, false))
);
println("Spark dataframe:");
Dataset<Row> df = spark.createDataFrame(rows, schema);
df.show();
}
}
输出如下:
Spark version:
2.4.3
Timestamp 1:
2019-01-01 01:00:00.0
Instant 1:
2019-01-01T06:00:00Z
Timestamp 2:
2019-01-01 02:00:00.0
Instant 2:
2019-01-01T07:00:00Z
Spark dataframe:
+-------------------+
| timestamp|
+-------------------+
|2019-01-01 01:00:00|
|2019-01-01 02:00:00|
+-------------------+
数据帧中的时间戳与我用来创建原始 Java 时间戳的文本输入相匹配,但底层时刻则不然。 (我在 EST5EDT 中运行它,因此 Timestamp 对象表示 EST5EDT 中的时间,而 Instant 对象在转换为字符串时以 UTC 表示。这完全是预期的。)
我的问题是这样的:
Spark 是使用时间戳对象的运行时 Java 表示来构建数据帧,还是使用 UTC 时刻,然后当我在数据帧上调用 show() 时简单地将它们显示在 EST5EDT 中?换句话说:java中时间戳的字符串表示形式与数据帧的内容之间是否存在确定性关系 或者 UTC时间轴上的时刻与数据帧的内容之间是否存在确定性关系?我知道,无论运行此代码的时区如何,df.show() 的输出都将是相同的,因为上述两种情况都会导致 show() 产生相同的输出。但是,如果我将数据帧的内容保存到 parquet,无论我的代码在哪个时区运行,我最终都会得到相同的结果吗?换句话说,如果我将此数据帧保存到 parquet,然后在具有不同本地时区的另一个环境中将其读入 Spark,数据帧是否相同?或者底层 UTC 时间将是相同的,这意味着本地表示将取决于我运行的本地时区?
最佳答案
我决定通过运行一些测试来回答我自己的问题。
如果将 Spark 数据帧中的时间戳读入不同时区的计算机上的数据帧,则写入 parquet 的时间戳将不同。换句话说,spark 似乎将 UTC 时间轴上的基础时刻的值保存到 parquet,然后在读取它的系统上处于 Activity 状态的任何本地时区中显示它。下面的测试证明了这一点:
我们需要的几个辅助函数:
void printStats(SparkSession spark, Timestamp timestamp1, Timestamp timestamp2, Dataset<Row> df) {
println("Spark version:");
println(spark.version());
println("");
println("Timezone:");
println(System.getProperty("user.timezone"));
println("Timestamp 1:");
println(timestamp1.toString());
println("Instant 1:");
println(timestamp1.toInstant().toString());
println("");
println("Timestamp 2:");
println(timestamp2.toString());
println("Instant 2:");
println(timestamp2.toInstant().toString());
println("");
println("Spark dataframe:");
df.show();
println("");
}
Dataset<Row> createDataframe(SparkSession spark, Timestamp timestamp1, Timestamp timestamp2) {
List<Row> rows = Arrays.asList(
RowFactory.create(timestamp1),
RowFactory.create(timestamp2)
);
StructType schema = DataTypes.createStructType(
Collections.singletonList(DataTypes.createStructField("timestamp", DataTypes.TimestampType, false))
);
return spark.createDataFrame(rows, schema);
}
首先在 EST 中写入一些时间戳以与机器进行 Parquet :
SparkSession spark = SparkSessionBuilder.getTestSparkSession();
Timestamp timestamp1 = Timestamp.valueOf("2019-01-01 01:00:00");
Timestamp timestamp2 = Timestamp.valueOf("2019-01-01 02:00:00");
Dataset<Row> df = createDataframe(spark, timestamp1, timestamp2);
printStats(spark, timestamp1, timestamp2, df);
String tempPath = "/temp/timestamps_test";
df.write().parquet(tempPath);
控制台输出:
Timezone:
America/New_York
Timestamp 1:
2019-01-01 01:00:00.0
Instant 1:
2019-01-01T06:00:00Z
Timestamp 2:
2019-01-01 02:00:00.0
Instant 2:
2019-01-01T07:00:00Z
Spark dataframe:
+-------------------+
| timestamp|
+-------------------+
|2019-01-01 01:00:00|
|2019-01-01 02:00:00|
+-------------------+
现在,我们将机器切换到 UTC 并将时间戳读回到新的数据帧中:
SparkSession spark = SparkSessionBuilder.getTestSparkSession();
String tempPath = "/temp/timestamps_test";
Dataset<Row> readDf = spark.read().parquet(tempPath);
Timestamp retrieved1 = (Timestamp) readDf.collectAsList().stream().map(r -> r.getTimestamp(0)).toArray()[0];
Timestamp retrieved2 = (Timestamp) readDf.collectAsList().stream().map(r -> r.getTimestamp(0)).toArray()[1];
printStats(spark, retrieved1, retrieved2, readDf);
输出:
Timezone:
UTC
Timestamp 1:
2019-01-01 06:00:00.0
Instant 1:
2019-01-01T06:00:00Z
Timestamp 2:
2019-01-01 07:00:00.0
Instant 2:
2019-01-01T07:00:00Z
Spark dataframe:
+-------------------+
| timestamp|
+-------------------+
|2019-01-01 06:00:00|
|2019-01-01 07:00:00|
+-------------------+
请注意,无论时区如何,时刻都是相同的,这表明 parquet 中存储的是 UTC 时刻,而不是本地时间戳。
关于java - 由 java 时间戳构造并写入 parquet 的 Spark 数据帧的内容是否会根据系统的本地时区而有所不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59274810/
目前正在学习 Spark 的类(class)并了解到执行者的定义: Each executor will hold a chunk of the data to be processed. Thisc
阅读了有关 http://spark.apache.org/docs/0.8.0/cluster-overview.html 的一些文档后,我有一些问题想要澄清。 以 Spark 为例: JavaSp
Spark核心中的调度器与以下Spark Stack(来自Learning Spark:Lightning-Fast Big Data Analysis一书)中的Standalone Schedule
我想在 spark-submit 或 start 处设置 spark.eventLog.enabled 和 spark.eventLog.dir -all level -- 不要求在 scala/ja
我有来自 SQL Server 的数据,需要在 Apache Spark (Databricks) 中进行操作。 在 SQL Server 中,此表的三个键列使用区分大小写的 COLLATION 选项
所有这些有什么区别和用途? spark.local.ip spark.driver.host spark.driver.bind地址 spark.driver.hostname 如何将机器修复为 Sp
我有大约 10 个 Spark 作业,每个作业都会进行一些转换并将数据加载到数据库中。必须为每个作业单独打开和关闭 Spark session ,每次初始化都会耗费时间。 是否可以只创建一次 Spar
/Downloads/spark-3.0.1-bin-hadoop2.7/bin$ ./spark-shell 20/09/23 10:58:45 WARN Utils: Your hostname,
我是 Spark 的完全新手,并且刚刚开始对此进行更多探索。我选择了更长的路径,不使用任何 CDH 发行版安装 hadoop,并且我从 Apache 网站安装了 Hadoop 并自己设置配置文件以了解
TL; 博士 Spark UI 显示的内核和内存数量与我在使用 spark-submit 时要求的数量不同 更多细节: 我在独立模式下运行 Spark 1.6。 当我运行 spark-submit 时
spark-submit 上的文档说明如下: The spark-submit script in Spark’s bin directory is used to launch applicatio
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6 个月前关闭。 Improve
我想了解接收器如何在 Spark Streaming 中工作。根据我的理解,将有一个接收器任务在执行器中运行,用于收集数据并保存为 RDD。当调用 start() 时,接收器开始读取。需要澄清以下内容
有没有办法在不同线程中使用相同的 spark 上下文并行运行多个 spark 作业? 我尝试使用 Vertx 3,但看起来每个作业都在排队并按顺序启动。 如何让它在相同的 spark 上下文中同时运行
我们有一个 Spark 流应用程序,这是一项长期运行的任务。事件日志指向 hdfs 位置 hdfs://spark-history,当我们开始流式传输应用程序时正在其中创建 application_X
我们正在尝试找到一种加载 Spark (2.x) ML 训练模型的方法,以便根据请求(通过 REST 接口(interface))我们可以查询它并获得预测,例如http://predictor.com
Spark newb 问题:我在 spark-sql 中进行完全相同的 Spark SQL 查询并在 spark-shell . spark-shell版本大约需要 10 秒,而 spark-sql版
我正在使用 Spark 流。根据 Spark 编程指南(参见 http://spark.apache.org/docs/latest/programming-guide.html#accumulato
我正在使用 CDH 5.2。我可以使用 spark-shell 运行命令。 如何运行包含spark命令的文件(file.spark)。 有没有办法在不使用 sbt 的情况下在 CDH 5.2 中运行/
我使用 Elasticsearch 已经有一段时间了,但使用 Cassandra 的经验很少。 现在,我有一个项目想要使用 Spark 来处理数据,但我需要决定是否应该使用 Cassandra 还是
我是一名优秀的程序员,十分优秀!