Spark Load is an asynchronous bulk import method that uses external Spark cluster resources to preprocess and load data into Doris. It is designed for initial large-scale data migrations from Hadoop Distributed File System (HDFS) or Hive tables—data volumes of more than 10 GB to terabytes—where offloading ETL work to Spark significantly reduces the compute load on your Doris cluster.
Submit and manage Spark Load jobs using the MySQL protocol. View job status with the SHOW LOAD command.
For smaller data volumes or data stored outside Spark-accessible systems, use Stream Load or Broker Load instead. Broker Load requires no Spark cluster but consumes more Doris cluster resources.
Prerequisites
Before you begin, ensure that you have:
A running Spark cluster (version 2.4.5 or later)
A running Hadoop cluster with YARN (version 2.5.2 or later) if using YARN mode
Access to HDFS or a Hive table containing your source data
USAGE_PRIVpermission on the Spark resource in Dorisenable_spark_loadset totrueinfe.conf
Key concepts
Spark ETL The ETL job runs on Spark and preprocesses data before it enters Doris. Preprocessing includes building global dictionaries (for BITMAP columns), partitioning, sorting, and aggregating data.
Broker An independent stateless process that provides Doris with read access to remote storage systems such as HDFS. The frontend (FE) node and backend (BE) nodes use brokers to transfer ETL output files.
Global dictionary A mapping structure that converts raw column values to integer-encoded values. Required when importing data into BITMAP aggregate columns using roaring bitmaps. A global dictionary can only be created when the data source is a Hive table.
Use cases
Spark Load is suited for:
Initial bulk migration: Loading more than 10 GB to TBs of historical data into Doris for the first time
HDFS-based sources: Data stored in HDFS or Hive tables accessible from Spark
BITMAP preprocessing: Data with columns that require global dictionary encoding before import
How it works
Submit a Spark Load job through the MySQL client. The FE node records metadata and returns a success acknowledgment. The job then runs through five stages:
|
+----v----+
| FE |---------------------------------+
+----+----+ |
| 3. FE send push tasks |
| 5. FE publish version |
+------------+------------+ |
| | | |
+---v---+ +---v---+ +---v---+ |
| BE | | BE | | BE | |1. FE submit Spark ETL job
+---^---+ +---^---+ +---^---+ |
|4. BE push with broker | |
+---+---+ +---+---+ +---+---+ |
|Broker | |Broker | |Broker | |
+---^---+ +---^---+ +---^---+ |
| | | |
+---+------------+------------+---+ 2.ETL +-------------v---------------+
| HDFS +-------> Spark cluster |
| <-------+ |
+---------------------------------+ +-----------------------------+The FE node submits an extract, transform, and load (ETL) job to the Spark cluster.
The Spark cluster runs the ETL job: builds global dictionaries, partitions, sorts, and aggregates data.
The FE node retrieves the preprocessed data directories and schedules BE nodes to run push jobs.
BE nodes pull files from HDFS using brokers and convert them into Doris storage format.
The FE node publishes a new version, completing the import.
Global dictionary
When it's needed
Doris BITMAP columns use roaring bitmaps, which require integer input. When importing data into BITMAP aggregate columns, Spark Load can build a global dictionary to encode raw values as integers during the ETL phase. The dictionary is stored as a Hive table structure mapping original values to encoded values.
Global dictionaries can only be created when importing from a Hive table, not from HDFS files directly.
How it's built
Read source data into a temporary Hive table (
hive_table).Deduplicate values and store distinct raw values in
distinct_value_table.Create a
dict_tablewith columns for raw values and encoded values.Perform a
LEFT JOINondistinct_value_tableanddict_table, encode new values using a window function, and write results back todict_table.Join
dict_tablewithhive_tableto replace raw values with encoded integers.Feed the encoded
hive_tableinto the remaining ETL pipeline for import into Doris.
Data preprocessing (DPP)
The Spark ETL job runs the following DPP steps:
Read data from HDFS or a Hive table.
Apply field mappings and expression-based transformations. Generate a
bucket_idfield for data bucketing based on partition metadata.Build rollup trees from Doris table rollup metadata.
Traverse rollup trees to aggregate data layer by layer, where each layer is derived from the previous one.
Distribute aggregated data to buckets based on
bucket_idand write to HDFS.Brokers pull the output files from HDFS and push them to Doris BE nodes.
Hive Bitmap UDF
Spark Load supports directly importing bitmap data generated in Hive into Doris using the Hive Bitmap UDF.
Configure a Spark resource
Before submitting a Spark Load job, register the Spark cluster as an external resource in Doris. Doris uses its Resource Management module to track and manage external resources.
Create a resource
CREATE EXTERNAL RESOURCE resource_name
PROPERTIES
(
type = spark,
spark_conf_key = spark_conf_value,
working_dir = path,
broker = broker_name,
broker.property_key = property_value,
broker.hadoop.security.authentication = kerberos,
broker.kerberos_principal = doris@YOUR.COM,
broker.kerberos_keytab = /home/doris/my.keytab
broker.kerberos_keytab_content = ASDOWHDLAWI********ALDJSDIWALD
)The following table describes the key parameters:
| Parameter | Required | Description |
|---|---|---|
type | Yes | Set to spark. |
spark.master | Yes | Set to yarn or spark://host:port. |
spark.submit.deployMode | Yes | Deployment mode: cluster or client. |
spark.hadoop.yarn.resourcemanager.address | When spark.master=yarn | YARN ResourceManager address. |
spark.hadoop.fs.defaultFS | When spark.master=yarn | Default HDFS filesystem address. |
working_dir | Yes (for ETL) | HDFS directory where ETL output is stored. Example: hdfs://host:port/tmp/doris. |
broker | Yes (for ETL) | Name of the broker registered with ALTER SYSTEM ADD BROKER. |
broker.property_key | No | Authentication properties for the broker to read ETL intermediate files. |
broker.hadoop.security.authentication | When using Kerberos | Set to kerberos. |
broker.kerberos_principal | When using Kerberos | Kerberos principal for authentication. |
broker.kerberos_keytab | When using Kerberos | Path to the keytab file on the broker server. |
broker.kerberos_keytab_content | When using Kerberos | Base64-encoded content of the keytab file. Use either this or broker.kerberos_keytab. |
For a full list of Spark configuration parameters, see Spark Configuration.
Example: YARN cluster mode
CREATE EXTERNAL RESOURCE "spark0"
PROPERTIES
(
"type" = "spark",
"spark.master" = "yarn",
"spark.submit.deployMode" = "cluster",
"spark.jars" = "xxx.jar,yyy.jar",
"spark.files" = "/tmp/aaa,/tmp/bbb",
"spark.executor.memory" = "1g",
"spark.yarn.queue" = "queue0",
"spark.hadoop.yarn.resourcemanager.address" = "127.0.0.1:9999",
"spark.hadoop.fs.defaultFS" = "hdfs://127.0.0.1:10000",
"working_dir" = "hdfs://127.0.0.1:10000/tmp/doris",
"broker" = "broker0",
"broker.username" = "user0",
"broker.password" = "password0"
);Example: Spark standalone client mode
CREATE EXTERNAL RESOURCE "spark1"
PROPERTIES
(
"type" = "spark",
"spark.master" = "spark://127.0.0.1:7777",
"spark.submit.deployMode" = "client",
"working_dir" = "hdfs://127.0.0.1:10000/tmp/doris",
"broker" = "broker1"
);Example: Kerberos-authenticated cluster
CREATE EXTERNAL RESOURCE "spark_on_kerberos"
PROPERTIES
(
"type" = "spark",
"spark.master" = "yarn",
"spark.submit.deployMode" = "cluster",
"spark.jars" = "xxx.jar,yyy.jar",
"spark.files" = "/tmp/aaa,/tmp/bbb",
"spark.executor.memory" = "1g",
"spark.yarn.queue" = "queue0",
"spark.hadoop.yarn.resourcemanager.address" = "127.0.0.1:9999",
"spark.hadoop.fs.defaultFS" = "hdfs://127.0.0.1:10000",
"working_dir" = "hdfs://127.0.0.1:10000/tmp/doris",
"broker" = "broker0",
"broker.hadoop.security.authentication" = "kerberos",
"broker.kerberos_principal" = "doris@YOUR.COM",
"broker.kerberos_keytab" = "/home/doris/my.keytab"
);Manage resources
View resources
SHOW RESOURCES
SHOW PROC "/resources"Ordinary accounts can only see resources for which they have USAGE_PRIV. Root and admin accounts see all resources.
Grant and revoke permissions
-- Grant USAGE_PRIV on a specific resource to a user
GRANT USAGE_PRIV ON RESOURCE "spark0" TO "user0"@"%";
-- Grant USAGE_PRIV on a specific resource to a role
GRANT USAGE_PRIV ON RESOURCE "spark0" TO ROLE "role0";
-- Grant USAGE_PRIV on all resources to a user
GRANT USAGE_PRIV ON RESOURCE * TO "user0"@"%";
-- Grant USAGE_PRIV on all resources to a role
GRANT USAGE_PRIV ON RESOURCE * TO ROLE "role0";
-- Revoke USAGE_PRIV on a specific resource from a user
REVOKE USAGE_PRIV ON RESOURCE "spark0" FROM "user0"@"%";Drop a resource
DROP RESOURCE resource_nameConfigure the Spark client
The FE node runs spark-submit internally to dispatch Spark Load jobs. Configure the Spark client on the FE node before submitting any jobs. Download Spark 2.4.5 or a later 2.x version.
Configure the Spark home directory
Place the Spark client in a directory on the same machine as the FE node. Set spark_home_default_dir in fe.conf to point to this directory. The default value is lib/spark2x relative to the FE root. This parameter cannot be blank.
Configure the Spark dependency package
Package all JAR files in the Spark client's jars/ folder into a ZIP file. Set spark_resource_path in fe.conf to the path of this ZIP file. If left blank, the FE node looks for lib/spark2x/jars/spark-2x.zip in its root directory and returns an error if the file is not found.
When a Spark Load job is submitted, the dependency package is uploaded to a remote directory in HDFS. The remote path follows this structure:
__spark_repository__spark0/
|-__archive_1.0.0/
| |-__lib_990325d2c0d1d5e45bf675e54e44fb16_spark-dpp-1.0.0-jar-with-dependencies.jar
| |-__lib_7670c29daf535efe3c9b923f778f61fc_spark-2x.zip
|-__archive_1.1.0/
| |-__lib_64d5696f99c379af2bee28c1c84271d5_spark-dpp-1.1.0-jar-with-dependencies.jar
| |-__lib_1bbb74bb6b264a270bc7fca3e964160f_spark-2x.zip
|-__archive_1.2.0/
| |-...The remote path is located in working_dir/{cluster_id} and named _spark_repository_{resource_name}. The FE node also uploads the Dynamic Partition Pruning (DPP) dependency package alongside spark-2x.zip. If the dependency files already exist in the remote repository, they are not re-uploaded.
Configure the YARN client
The FE node uses YARN commands to query application status and terminate applications. Configure the YARN client on the FE node. Download Hadoop 2.5.2 or a later 2.x version.
Configure the YARN executable path
Place the YARN client on the same machine as the FE node. Set yarn_client_path in fe.conf to the path of the YARN binary executable. The default value is lib/yarn-client/hadoop/bin/yarn relative to the FE root.
Configure the YARN config directory (optional)
When the FE node runs YARN commands, it generates core-site.xml and yarn-site.xml in a temporary config directory. The default path is lib/yarn-config relative to the FE root. To change this path, set yarn_config_dir in fe.conf.
Submit a Spark Load job
For the full syntax reference, run HELP SPARK LOAD in the MySQL client.
Syntax
LOAD LABEL load_label
(data_desc, ...)
WITH RESOURCE resource_name
[resource_properties]
[PROPERTIES (key1=value1, ... )]
-- load_label:
db_name.label_name
-- data_desc (HDFS file):
DATA INFILE ('file_path', ...)
[NEGATIVE]
INTO TABLE tbl_name
[PARTITION (p1, p2)]
[COLUMNS TERMINATED BY separator]
[(col1, ...)]
[COLUMNS FROM PATH AS (col2, ...)]
[SET (k1=f1(xx), k2=f2(xx))]
[WHERE predicate]
-- data_desc (Hive table):
DATA FROM TABLE hive_external_tbl
[NEGATIVE]
INTO TABLE tbl_name
[PARTITION (p1, p2)]
[SET (k1=f1(xx), k2=f2(xx))]
[WHERE predicate]
-- resource_properties:
(key2=value2, ...)Supported data sources are CSV files in HDFS and Hive external tables. Other rules follow Broker Load conventions.
Parameters
Data description parameters
Only CSV files and Hive tables are supported as data sources. Other rules are consistent with Broker Load.
Job parameters
Job parameters (set in PROPERTIES) apply to the entire import job and follow the same rules as Broker Load.
Per-job Spark resource overrides
To override Spark resource settings for a single job without changing the cluster-level resource configuration, specify overrides inline:
WITH RESOURCE 'spark0'
(
"spark.driver.memory" = "1g",
"spark.executor.memory" = "3g"
)Overrides apply only to the current job.
Examples
Example 1: Import from HDFS files
LOAD LABEL db1.label1
(
DATA INFILE("hdfs://abc.com:8888/user/palo/test/ml/file1")
INTO TABLE tbl1
COLUMNS TERMINATED BY ","
(tmp_c1,tmp_c2)
SET
(
id=tmp_c2,
name=tmp_c1
),
DATA INFILE("hdfs://abc.com:8888/user/palo/test/ml/file2")
INTO TABLE tbl2
COLUMNS TERMINATED BY ","
(col1, col2)
where col1 > 1
)
WITH RESOURCE 'spark0'
(
"spark.executor.memory" = "2g",
"spark.shuffle.compress" = "true"
)
PROPERTIES
(
"timeout" = "3600"
);Example 2: Import from a Hive table
First, create an external Hive table in Doris:
CREATE EXTERNAL TABLE hive_t1
(
k1 INT,
K2 SMALLINT,
k3 varchar(50),
uuid varchar(100)
)
ENGINE=hive
properties
(
"database" = "tmp",
"table" = "t1",
"hive.metastore.uris" = "thrift://0.0.0.0:8080"
);Then submit the load job. The columns in the Doris target table must exist in the external Hive table:
LOAD LABEL db1.label1
(
DATA FROM TABLE hive_t1
INTO TABLE tbl1
SET
(
uuid=bitmap_dict(uuid)
)
)
WITH RESOURCE 'spark0'
(
"spark.executor.memory" = "2g",
"spark.shuffle.compress" = "true"
)
PROPERTIES
(
"timeout" = "3600"
);Example 3: Import BINARY bitmap data from a Hive table
Use this approach when the source Hive column is of type BINARY and the data was serialized using the org.apache.doris.load.loadv2.dpp.BitmapValue class from spark-dpp.
Create the external Hive table:
CREATE EXTERNAL TABLE hive_t1
(
k1 INT,
K2 SMALLINT,
k3 varchar(50),
uuid varchar(100) -- BINARY type in the Hive table
)
ENGINE=hive
properties
(
"database" = "tmp",
"table" = "t1",
"hive.metastore.uris" = "thrift://0.0.0.0:8080"
);Submit the load job using binary_bitmap:
LOAD LABEL db1.label1
(
DATA FROM TABLE hive_t1
INTO TABLE tbl1
SET
(
uuid=binary_bitmap(uuid)
)
)
WITH RESOURCE 'spark0'
(
"spark.executor.memory" = "2g",
"spark.shuffle.compress" = "true"
)
PROPERTIES
(
"timeout" = "3600"
);binary_bitmap requires a Hive table as the data source.
Example 4: Import from a partitioned Hive table
Hive table definition:
CREATE TABLE test_partition(
id int,
name string,
age int
)
PARTITIONED BY (dt string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE;Doris target table definition:
CREATE TABLE IF NOT EXISTS test_partition_04
(
dt date,
id int,
name string,
age int
)
UNIQUE KEY(`dt`, `id`)
DISTRIBUTED BY HASH(`id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);Create the Spark resource and submit the load job:
CREATE EXTERNAL RESOURCE "spark_resource"
PROPERTIES
(
"type" = "spark",
"spark.master" = "yarn",
"spark.submit.deployMode" = "cluster",
"spark.executor.memory" = "1g",
"spark.yarn.queue" = "default",
"spark.hadoop.yarn.resourcemanager.address" = "localhost:50056",
"spark.hadoop.fs.defaultFS" = "hdfs://localhost:9000",
"working_dir" = "hdfs://localhost:9000/tmp/doris",
"broker" = "broker_01"
);
LOAD LABEL demo.test_hive_partition_table_18
(
DATA INFILE("hdfs://localhost:9000/user/hive/warehouse/demo.db/test/dt=2022-08-01/*")
INTO TABLE test_partition_04
COLUMNS TERMINATED BY ","
FORMAT AS "csv"
(id,name,age)
COLUMNS FROM PATH AS (`dt`)
SET
(
dt=dt,
id=id,
name=name,
age=age
)
)
WITH RESOURCE 'spark_resource'
(
"spark.executor.memory" = "1g",
"spark.shuffle.compress" = "true"
)
PROPERTIES
(
"timeout" = "3600"
);Global dictionary in load jobs
When the target Doris table has a BITMAP aggregate column, specify bitmap_dict in the SET clause to trigger global dictionary creation:
SET (doris_field_name = bitmap_dict(hive_field_name))Global dictionary creation is only supported when the data source is a Hive table.
View import jobs
Spark Load jobs are asynchronous. Record the job label when you submit a job, then use it to check status:
SHOW LOAD ORDER BY createtime DESC LIMIT 1\GExample output:
*************************** 1. row ***************************
JobId: 76391
Label: label1
State: FINISHED
Progress: ETL:100%; LOAD:100%
Type: SPARK
EtlInfo: unselected.rows=4; dpp.abnorm.ALL=15; dpp.norm.ALL=28133376
TaskInfo: cluster:cluster0; timeout(s):10800; max_filter_ratio:5.0E-5
ErrorMsg: N/A
CreateTime: 2019-07-27 11:46:42
EtlStartTime: 2019-07-27 11:46:44
EtlFinishTime: 2019-07-27 11:49:44
LoadStartTime: 2019-07-27 11:49:44
LoadFinishTime: 2019-07-27 11:50:16
URL: http://1.1.*.*:80**/proxy/application_15866****3848_0035/
JobDetails: {"ScannedRows":28133395,"TaskNumber":1,"FileNumber":1,"FileSize":200000}Spark Load-specific fields differ from Broker Load as follows:
| Field | Description |
|---|---|
State | Job lifecycle: PENDING → ETL → LOADING → FINISHED (or CANCELLED on failure). |
Progress | Two components: ETL (Spark preprocessing progress) and LOAD (BE push progress). LOAD progress is calculated as: number of imported tablets in all replicas / total number of tablets in the import job × 100%. LOAD reaches 99% when all tablets are pushed; it becomes 100% only after the version is published. |
Type | Always SPARK for Spark Load jobs. |
JobDetails | Updated after the ETL phase. Includes scanned rows, task count, file count, and file size. |
URL | Link to the YARN application page for the ETL job. |
Import progress is not linear. A period without progress does not necessarily mean the job is stuck.
For a complete description of all fields, see Broker Load.
View logs
Spark Load generates a log file when a job is submitted. Logs are stored at:
{FE_ROOT}/log/spark_launcher_log/spark_launcher_{load_job_id}_{label}.logLogs are retained for three days and deleted together with the job metadata from the FE node.
Cancel a job
If the import job is not in the FINISHED or CANCELLED state, you can cancel the import job by specifying its label. For the full syntax, run HELP CANCEL LOAD.
System configurations
The following fe.conf parameters apply globally to all Spark Load jobs:
| Parameter | Default | Description |
|---|---|---|
enable_spark_load | false | Enable Spark Load and external resource creation. Set to true to activate. |
spark_load_default_timeout_second | 259200 (3 days) | Default job timeout in seconds. |
spark_home_default_dir | fe/lib/spark2x | Root directory of the Spark client. |
spark_resource_path | (empty) | Path to the packaged Spark dependency ZIP file. |
spark_launcher_log_dir | fe/log/spark_launcher_log | Directory for Spark Load log files. |
yarn_client_path | fe/lib/yarn-client/hadoop/bin/yarn | Path to the YARN binary executable. |
yarn_config_dir | fe/lib/yarn-config | Directory where YARN config files (core-site.xml, yarn-site.xml) are generated. |
What's next
Broker Load — simpler import method for smaller datasets or non-Spark environments
Stream Load — synchronous import for real-time or small-batch scenarios