blob: f80c4b2c77c47995583ff81faa12f6550e0c5b80 [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Apache Spark
## 1. 功能概述
IoTDB 提供 `Spark-IoTDB-Connector` 作为实现 IoTDB 树模型的 Spark 连接器,支持在 Spark 环境中对 IoTDB 树模型的数据进行读写。
## 2. 兼容性要求
| 软件 | 版本 |
| ------------- | -------------- |
| `Spark` | 2.4.0-latest |
| `Scala` | 2.11, 2.12 |
* `spark-iotdb-connector` 支持在 Java、Scala 版本的 Spark 与 PySpark 中使用。
## 3. 部署方式
`spark-iotdb-connector` 共有两个使用场景,分别为 IDE 开发与 spark-shell 调试。
### 3.1 IDE 开发
在 IDE 开发时,只需要在 `pom.xml` 文件中添加以下依赖即可。
```XML
<dependency>
<groupId>org.apache.iotdb</groupId>
<!-- spark-iotdb-connector_2.11 or spark-iotdb-connector_2.13 -->
<artifactId>spark-iotdb-connector_2.12.10</artifactId>
<version>${iotdb.version}</version>
</dependency>
```
### 3.2 `spark-shell` 调试
在 `spark-shell` 中使用 `spark-iotdb-connetcor`,可参考如下步骤:
* 通过官网下载 `with-dependencies` 版本的 jar 包
* 通过如下命令将 Jar 包拷贝到 `${SPARK_HOME}/jars` 目录中即可。
```Bash
cp spark-iotdb-connector_2.12.10-${iotdb.version}.jar $SPARK_HOME/jars/
```
为了保证 spark 能使用 JDBC 和 IoTDB 连接,需要进行如下操作:
* 运行如下命令来编译 IoTDB-JDBC 连接器
```Bash
mvn clean package -pl iotdb-client/jdbc -am -DskipTests -P get-jar-with-dependencies
```
* 编译后的 jar 包在如下目录中
```Bash
$IoTDB_HOME/iotdb-client/jdbc/target/iotdb-jdbc-{version}-SNAPSHOT-jar-with-dependencies.jar
```
* 运行如下命令将 jar 包拷贝到 `${SPARK_HOME}/jars` 目录中即可
```Bash
cp iotdb-jdbc-{version}-SNAPSHOT-jar-with-dependencies.jar $SPARK_HOME/jars/
```
## 4. 使用方式
### 4.1 参数介绍
| **参数** | **描述** | **默认值** | **使用范围** | **能否为空** |
| ---------------- | ---------------------------------------------------------------------- | ------------------ | -------------------- | -------------------- |
| url | 指定 IoTDB 的 JDBC 的 URL | null | read、write | FALSE |
| user | IoTDB 的用户名 | root | read、write | TRUE |
| password | IoTDB 的密码 | root | read、write | TRUE |
| sql | 用于指定查询的 SQL 语句 | null | read | TRUE |
| numPartition | 在 read 中用于指定 DataFrame 的分区数,在 write 中用于设置写入并发数 | 1 | read、write | TRUE |
| lowerBound | 查询的起始时间戳(包含) | 0 | read | TRUE |
| upperBound | 查询的结束时间戳(包含) | 0 | read | TRUE |
### 4.2 读取数据
* 从 IoTDB 中读取数据成为 DataFrame
```scala
import org.apache.iotdb.spark.db._
val df = spark.read.format("org.apache.iotdb.spark.db")
.option("user", "root")
.option("password", "root")
.option("url", "jdbc:iotdb://127.0.0.1:6667/")
.option("sql", "select ** from root") // 查询 SQL
.option("lowerBound", "0") // 时间戳下界
.option("upperBound", "100000000") // 时间戳上界
.option("numPartition", "5") // 分区数
.load
df.printSchema()
df.show()
```
### 4.3 写入数据
```scala
// 构造窄表数据
val df = spark.createDataFrame(List(
(1L, "root.test.d0", 1, 1L, 1.0F, 1.0D, true, "hello"),
(2L, "root.test.d0", 2, 2L, 2.0F, 2.0D, false, "world")))
val dfWithColumn = df.withColumnRenamed("_1", "Time")
.withColumnRenamed("_2", "Device")
.withColumnRenamed("_3", "s0")
.withColumnRenamed("_4", "s1")
.withColumnRenamed("_5", "s2")
.withColumnRenamed("_6", "s3")
.withColumnRenamed("_7", "s4")
.withColumnRenamed("_8", "s5")
// 写入窄表数据
dfWithColumn
.write
.format("org.apache.iotdb.spark.db")
.option("url", "jdbc:iotdb://127.0.0.1:6667/")
.save
// 构造宽表数据
val df = spark.createDataFrame(List(
(1L, 1, 1L, 1.0F, 1.0D, true, "hello"),
(2L, 2, 2L, 2.0F, 2.0D, false, "world")))
val dfWithColumn = df.withColumnRenamed("_1", "Time")
.withColumnRenamed("_2", "root.test.d0.s0")
.withColumnRenamed("_3", "root.test.d0.s1")
.withColumnRenamed("_4", "root.test.d0.s2")
.withColumnRenamed("_5", "root.test.d0.s3")
.withColumnRenamed("_6", "root.test.d0.s4")
.withColumnRenamed("_7", "root.test.d0.s5")
// 写入宽表数据
dfWithColumn.write.format("org.apache.iotdb.spark.db")
.option("url", "jdbc:iotdb://127.0.0.1:6667/")
.option("numPartition", "10")
.save
```
## 5. 宽表与窄表
### 5.1 数据格式示例
以 TsFile 结构为例,假设 TsFile 模式中有三个度量:状态,温度和硬件。
* 基本信息如下:
| 名称 | 类型 | 编码 |
| ------ | --------- | ------- |
| 状态 | Boolean | PLAIN |
| 温度 | Float | RLE |
| 硬件 | Text | PLAIN |
* 数据如下:
* `d1:root.ln.wf01.wt01`
* `d2:root.ln.wf02.wt02`
| time | d1.status | time | d1.temperature | time | d2.hardware | time | d2.status |
| ------ | ----------- | ------ | ---------------- | ------ | ------------- | ------ | ----------- |
| 1 | True | 1 | 2.2 | 2 | "aaa" | 1 | True |
| 3 | True | 2 | 2.2 | 4 | "bbb" | 2 | False |
| 5 | False | 3 | 2.1 | 6 | "ccc" | 4 | True |
* 宽表(默认)形式如下:
| Time | root.ln.wf02.wt02.temperature | root.ln.wf02.wt02.status | root.ln.wf02.wt02.hardware | root.ln.wf01.wt01.temperature | root.ln.wf01.wt01.status | root.ln.wf01.wt01.hardware |
| ------ | ------------------------------- | -------------------------- | ---------------------------- | ------------------------------- | -------------------------- | ---------------------------- |
| 1 | null | true | null | 2.2 | true | null |
| 2 | null | false | aaa | 2.2 | null | null |
| 3 | null | null | null | 2.1 | true | null |
| 4 | null | true | bbb | null | null | null |
| 5 | null | null | null | null | false | null |
| 6 | null | null | ccc | null | null | null |
* 窄表形式如下:
| Time | Device | status | hardware | temperature |
| ------ | ------------------- | -------- | ---------- | ------------- |
| 1 | root.ln.wf02.wt01 | true | null | 2.2 |
| 1 | root.ln.wf02.wt02 | true | null | null |
| 2 | root.ln.wf02.wt01 | null | null | 2.2 |
| 2 | root.ln.wf02.wt02 | false | aaa | null |
| 3 | root.ln.wf02.wt01 | true | null | 2.1 |
| 4 | root.ln.wf02.wt02 | true | bbb | null |
| 5 | root.ln.wf02.wt01 | false | null | null |
| 6 | root.ln.wf02.wt02 | null | ccc | null |
### 5.2 数据转换示例
* 从宽表到窄表
```scala
import org.apache.iotdb.spark.db._
val wide_df = spark.read.format("org.apache.iotdb.spark.db").option("url", "jdbc:iotdb://127.0.0.1:6667/").option("sql", "select * from root.** where time < 1100 and time > 1000").load
val narrow_df = Transformer.toNarrowForm(spark, wide_df)
```
* 从窄表到宽表
```scala
import org.apache.iotdb.spark.db._
val wide_df = Transformer.toWideForm(spark, narrow_df)
```