tree: e62a67e58936f8b69f0564424ba99a3d8a668fe9
  1. .env.example
  2. .gitignore
  3. demo.dml
  4. deploy.sh
  5. README.md
  6. SystemDS_Delta_E2E.scala
  7. SystemDS_MLContext_Demo.scala
scripts/databricks/README.md

Running SystemDS on Databricks

Scripts and demo notebooks for deploying and running SystemDS on a Databricks cluster. Tested against DBR 16.4 LTS (Spark 3.5.2 / Scala 2.12), where the SystemDS jar runs unchanged.

Contents

FilePurpose
deploy.shCreate a UC volume, upload SystemDS.jar, create a single-user cluster, install the Delta Kernel libraries, and import the demo notebooks.
SystemDS_MLContext_Demo.scalaNotebook: Unity Catalog round-trip using the SystemDS MLContext (Scala) API. Reads a table, runs a configurable DML script, writes the result back.
SystemDS_Delta_E2E.scalaNotebook: end-to-end Delta → linear regression on one Delta table. SystemDS reads it natively as a frame (read(format="delta")) → transformencodelm; Spark ML reads the same table → OneHotEncoderLinearRegression. Times read + encode + train for both.
demo.dmlStandalone DML smoke test: reads a matrix from storage, computes column sums and a Gram-matrix trace.
.env.exampleTemplate for your local configuration.

Prerequisites

  • The Databricks CLI installed and authenticated once interactively:

    databricks auth login --profile <your-profile>
    
  • A built SystemDS jar at <repo-root>/target/SystemDS.jar (mvn -q -DskipTests package), or set JAR_LOCAL to point at one.

  • python3 on your PATH (used to parse CLI JSON output).

Configuration

All settings are read from environment variables. The easiest way is a .env file:

cp scripts/databricks/.env.example scripts/databricks/.env
# then edit scripts/databricks/.env

deploy.sh looks for a .env file by:

  1. ENV_FILE=/abs/path/to/.env if you set it explicitly, otherwise
  2. searching upward from the script's own directory (script dir → repo root → any parent directory) for the first .env it finds.

Anything already exported in your shell overrides values from .env.

VariableDefaultDescription
PROFILEDEFAULTDatabricks CLI profile.
CATALOG / SCHEMA / VOLUMEmain / default / systemdsUC location for the jar volume (and notebook defaults).
POLICY_ID(empty)Compute policy id; leave empty for none.
SPARK_VERSION16.4.x-scala2.12DBR runtime.
NODE_TYPEi3.xlargeNode type.
NUM_WORKERS0Worker count (0 = single node).
AUTOTERMINATION_MINUTES30Auto-terminate idle minutes.
CLUSTER_NAMEsystemdsCluster name.
JAR_LOCAL<repo-root>/target/SystemDS.jarJar to upload.
NB_DIR/Users/<you>Workspace folder to import notebooks into.
NB_FILES(the 2 demo notebooks)Space-separated notebooks to import; language detected from extension.
DELTA_KERNEL_VERSION3.3.2Delta Kernel Maven library version installed by deploy.sh libs (>= 3.3.2; must match pom.xml).
USER_NAME(auto-detected)Databricks user.

Choosing a node type

NODE_TYPE is a cloud instance type. The default i3.xlarge is a small, storage-optimized AWS node (4 vCPU / 30.5 GiB RAM / 950 GB local NVMe SSD); the fast local disk is handy because the notebook spills SystemDS scratch to /local_disk0. With NUM_WORKERS=0 this single node is both driver and executor, so it bounds the total memory available to SystemDS.

Some common AWS options (pick more cores/RAM for larger workloads):

Node typevCPURAMLocal SSDNotes
i3.xlarge430.5 GiB950 GBDefault; storage-optimized.
i3.2xlarge861 GiB1900 GBSame family, 2× bigger.
i4i.xlarge432 GiB937 GBNewer gen, faster storage.
m5d.xlarge416 GiB150 GBGeneral purpose w/ local SSD.
r5d.2xlarge864 GiB300 GBMemory-optimized w/ local SSD.

The exact set depends on your cloud (AWS / Azure / GCP) and workspace. List what your workspace actually offers with:

databricks clusters list-node-types -p "$PROFILE" -o json

References: AWS EC2 instance types, Azure VM sizes, GCP machine families.

Usage

cd scripts/databricks
./deploy.sh upload     # create UC volume + copy SystemDS.jar into it
./deploy.sh cluster    # create the single-user cluster + install the jar
./deploy.sh libs       # install the Delta Kernel Maven libraries on the cluster
./deploy.sh import     # import the demo notebooks
./deploy.sh all        # all of the above

The created cluster id is written to scripts/databricks/.cluster_id.

Delta Kernel libraries

The Delta notebook (SystemDS_Delta_E2E) reads Delta tables natively through the Spark-free Delta Kernel, which is not on the DBR classpath. ./deploy.sh libs installs io.delta:delta-kernel-defaults (version DELTA_KERNEL_VERSION, default 3.3.2) as a cluster Maven library. Use >= 3.3.2: earlier releases trip a classloader conflict with DBR's bundled parquet. The version must match the delta-kernel.version property in the SystemDS pom.xml.

Notebook configuration (SystemDS_MLContext_Demo)

The Scala notebook is driven by widgets, so nothing is hardcoded — set them in the notebook UI or pass them as job parameters:

WidgetDefaultDescription
catalog / schemamain / defaultWhere the input/output tables live.
input_table / output_tablesystemds_input / systemds_outputTable names.
dml_path(blank)DML script to run. Blank uses the built-in z-score demo; otherwise a path readable from the driver (UC volume, /Workspace, or dbfs:).
exec_typeDEFAULTSystemDS execution mode. DEFAULT lets SystemDS choose the plan; DRIVER, SPARK, or DRIVER_AND_SPARK force a mode.

Custom DML contract: the script receives the input matrix as X and must produce a matrix Y and a scalar checksum.

Notebook configuration (SystemDS_Delta_E2E)

WidgetDefaultDescription
catalog / schema / volumemain / default / systemdsUC location; the Delta table is written under the volume.
rows1000000Rows in the generated Delta table.
num_numeric / num_categorical / cardinality100 / 20 / 30Feature shape. Defaults are deliberately encode-heavy (700 features) so the SystemDS-vs-Spark difference is visible.
reg1e-3L2 regularization for lm.
recreatetrueRewrite the Delta table before running.
statisticstruePrint the SystemDS per-instruction breakdown.

The encode complexity (categoricals × cardinality), not the row count, drives the gap: more categoricals blow up Spark's StringIndexer + OneHotEncoder (each a shuffle stage), while SystemDS dummycodes in-memory. On a single node, raw rows instead favor Spark, and very large tables can exhaust driver memory.

Indicative single-node (i3.xlarge, 1M rows) numbers — single cold run, no warmup:

workloadSpark MLSystemDSspeedup
SystemDS_Delta_E2E, 700 features (read + encode + train)116.6 s55.4 s~2.1×

The Spark side is the same speed on Spark 3.5.2 (DBR 16.4) and Spark 4.0.0 (DBR 17.3 LTS), so the comparison is not an artifact of an old runtime.

Notes / gotchas baked into the scripts

  • UC clusters only accept JAR libraries from a UC Volume (not DBFS, not /Workspace).
  • The cluster must be SINGLE_USER (Assigned) mode; shared / USER_ISOLATION blocks JAR libraries.
  • SystemDS needs the Vector API module plus a full --add-opens set at JVM launch (configured via spark.{driver,executor}.extraJavaOptions), and an absolute scratch dir (the notebook pins sysds.scratch).

.env and .cluster_id are git-ignored — they hold personal config and local state and should never be committed.