dbutils.fs.ls("/Volumes/main/dbx_course/raw") # list files
dbutils.fs.cp(src, dst, recurse=True) # copy (also mv, rm, mkdirs, head, put)
dbutils.widgets.text("run_date", "2025-01-01") # job parameter in a notebook
dbutils.widgets.get("run_date")
dbutils.secrets.get(scope="my_app", key="api_key") # value is redacted in output
dbutils.notebook.run("./child", 600, {"p": "x"}) # run another notebook
dbutils.notebook.exit("done") # return a value
dbutils.jobs.taskValues.set(key="n", value=5) # pass values between job tasks
dbutils.help() # list everything
Module 24: Cheat Sheets
Quick-reference cheat sheets for daily work and interviews.
Topics in this module
- Databricks Workspace Commands
- Notebook Magic Commands
- PySpark Built-in Functions
- Spark SQL Functions
- DataFrame Operations
- Join Types and Strategies
- Window Functions
- Delta Lake Commands
- Auto Loader Configuration
- Structured Streaming Options
- Lakeflow Pipeline Syntax
- Unity Catalog SQL Commands
- Lakeflow Jobs Configuration
- Performance Tuning Checklist
- Debugging and Troubleshooting
- Databricks CLI Commands
- Interview Quick Reference
Seventeen one-page cheat sheets. Tables first, one snippet each. Use them to look things up, not to learn from.
- Each sheet points to the module that teaches it
- Code is for reference: names like
ordersare from the practice data - Free Edition (serverless) differences are marked
- Print-friendly in spirit: skim a sheet before an interview or before building
Databricks Workspace Commands
By the end: find your way around the workspace and `dbutils`.
| Sidebar item | Use |
|---|---|
| Workspace | Notebooks, files, Git folders |
| Catalog | Browse catalogs, schemas, tables, volumes |
| Jobs & Pipelines | Jobs and Lakeflow pipelines |
| SQL Editor / Dashboards / Genie | SQL, reports, natural-language questions |
| Compute | Compute (serverless on Free Edition), SQL warehouse |
| Notebook shortcut | Does |
|---|---|
Shift+Enter |
Run cell, move on |
Ctrl/Cmd+Enter |
Run cell, stay |
Esc then A / B |
Insert cell above / below |
Esc then D D |
Delete cell |
Ctrl/Cmd+/ |
Comment the line |
display(df)for tables and charts;displayHTML(html)for HTML- Paths:
/Volumes/<catalog>/<schema>/<volume>/...for files,/Workspace/...for workspace files - Taught in Modules 2 to 4
Notebook Magic Commands
By the end: use magic commands to switch language or run shell and install packages.
| Magic | Does | Note |
|---|---|---|
%python %sql %scala %r |
Run the cell in that language | Default is the notebook language |
%md |
Markdown text cell | |
%run ./helpers |
Run another notebook in this session | Its functions and variables become available |
%pip install pkg |
Install a Python package for this session | Put at the top of the notebook |
%sh |
Shell command on the driver | Not for big data |
%pip install requests==2.32.3
dbutils.library.restartPython() # restart Python so new packages load
%runmust be alone in its cell%pipfirst, then restart: values in memory are lost- Prefer a wheel or Git-folder module over
%runfor real projects (Module 26)
PySpark Built-in Functions
By the end: recall the PySpark functions you use most, grouped by job.
from pyspark.sql import functions as F
| Job | Functions |
|---|---|
| Columns | col, lit, expr, when/otherwise, coalesce, nullif |
| Strings | trim, lower, upper, concat, concat_ws, substring, regexp_replace, regexp_extract, split, lpad, length |
| Numbers | round, floor, ceil, abs, pmod, greatest, least |
| Dates | current_date, to_date, to_timestamp, date_trunc, date_add, datediff, months_between, date_format, year, month |
| Aggregates | count, countDistinct, sum, avg, min, max, collect_list, collect_set, approx_count_distinct |
| Arrays and maps | array, explode, size, array_contains, collect_list, map_keys, transform |
| Structs and JSON | struct, from_json, to_json, get_json_object, col("a.b") |
| Null handling | isNull, isNotNull, coalesce, fillna, dropna |
| Hash and ids | hash, sha2, md5, monotonically_increasing_id, uuid |
| Windows | row_number, rank, dense_rank, lag, lead, ntile |
df.select(
F.col("order_id"),
F.when(F.col("quantity") >= 5, "bulk").otherwise("single").alias("size"),
F.date_trunc("month", "order_ts").alias("month"),
)
- Build columns with functions, not Python loops over rows (Module 5)
- Avoid Python UDFs when a built-in exists
Spark SQL Functions
By the end: recall the Spark SQL functions you use most.
| Job | SQL |
|---|---|
| Conditional | CASE WHEN ... END, IF(c, a, b), coalesce, nullif |
| Dates | date_trunc('month', ts), date_add, datediff, current_date() |
| Strings | concat_ws, regexp_replace, split, trim |
| Aggregate filter | count(*) FILTER (WHERE status = 'cancelled') |
| Grouping | GROUP BY ALL, ROLLUP, CUBE, GROUPING SETS |
| Windows | row_number() OVER (PARTITION BY ... ORDER BY ...) |
| Filter on a window | QUALIFY row_number() OVER (...) = 1 |
| Pivot | PIVOT (sum(x) FOR col IN ('a', 'b')) |
| Semi-structured | col:path::type, from_json, explode |
| Errors | try_cast, try_divide |
%sql
SELECT customer_id, order_id
FROM dbx_course.orders
QUALIFY row_number() OVER (PARTITION BY customer_id ORDER BY order_ts DESC) = 1
- On serverless, ANSI mode is on: a bad cast fails. Use
try_castwhen data may be dirty - Taught in Modules 4 and 13
DataFrame Operations
By the end: recall the DataFrame operations and their cost.
| Operation | Code | Shuffle? |
|---|---|---|
| Select / rename | select, withColumnRenamed, withColumns |
No |
| Filter | filter("qty > 0") |
No |
| Add column | withColumn("x", expr) |
No |
| Drop duplicates | dropDuplicates(["id"]) |
Yes |
| Group | groupBy("k").agg(...) |
Yes |
| Join | a.join(b, "k", "left") |
Usually yes |
| Sort | orderBy("x") |
Yes |
| Repartition | repartition(n, "k") |
Yes |
| Union | unionByName(b) |
No |
| Write | write.format("delta").saveAsTable(...) |
Action |
(df.filter("quantity > 0")
.withColumn("revenue", F.col("quantity") * F.col("price"))
.groupBy("customer_id").agg(F.sum("revenue").alias("total"))
.orderBy(F.desc("total"))
.limit(10)
.show())
- Transformations are lazy. Actions (
show,count,collect,write) run the plan - Look at the plan with
df.explain() - On serverless: no
df.rdd, andcache()is not available
Join Types and Strategies
By the end: pick the right join type and strategy.
| Join type | Keeps |
|---|---|
inner |
Matches only |
left |
All left rows, NULLs where no match |
right |
All right rows |
full |
All rows from both |
left_semi |
Left rows that have a match (no right columns) |
left_anti |
Left rows that have no match |
cross |
Every pair |
| Strategy | When |
|---|---|
| Broadcast hash | One side is small: sent to every task, no shuffle |
| Sort-merge | Both sides large |
| Shuffle hash | One side much smaller, not small enough to broadcast |
big.join(F.broadcast(small), "product_id", "left") # force a broadcast
spark.table("orders").join(spark.table("customers").hint("broadcast"), "customer_id")
SELECT /*+ BROADCAST(c) */ * FROM orders o JOIN customers c USING (customer_id)
- Anti-join for "rows missing from the other table"
- Join keys with NULLs never match (use
eqNullSafeif you need them to) - Taught in Modules 5 and 12
Window Functions
By the end: write window functions from memory.
| Need | Function |
|---|---|
| Rank within a group | row_number(), rank(), dense_rank() |
| Previous / next row | lag(col, n), lead(col, n) |
| Running total | sum(x) OVER (... ORDER BY ... ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) |
| Moving average | avg(x) OVER (... ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) |
| Share of total | x / sum(x) OVER () |
| Buckets | ntile(4) |
w = Window.partitionBy("customer_id").orderBy("order_ts")
w_run = w.rowsBetween(Window.unboundedPreceding, Window.currentRow)
df.select(
"customer_id", "order_ts",
F.row_number().over(w).alias("n"),
F.lag("order_ts").over(w).alias("prev_ts"),
F.sum("quantity").over(w_run).alias("running_qty"),
)
- Latest row per key:
row_number() ... ORDER BY ts DESC, then keepn = 1 - Always give an
ORDER BYthat breaks ties, or results change between runs - A window with no
PARTITION BYmoves all rows to one task
Delta Lake Commands
By the end: recall the Delta Lake commands.
| Task | SQL |
|---|---|
| Create | CREATE TABLE t (id INT, name STRING) |
| Insert / overwrite | INSERT INTO t ..., INSERT OVERWRITE t ... |
| Upsert | MERGE INTO t USING s ON t.id = s.id WHEN MATCHED THEN UPDATE SET * WHEN NOT MATCHED THEN INSERT * |
| Update / delete | UPDATE t SET ... WHERE ..., DELETE FROM t WHERE ... |
| History | DESCRIBE HISTORY t |
| Time travel | SELECT * FROM t VERSION AS OF 3, TIMESTAMP AS OF '2025-01-01' |
| Restore | RESTORE TABLE t TO VERSION AS OF 3 |
| Compact | OPTIMIZE t |
| Clean files | VACUUM t (default keeps 7 days) |
| Cluster | CREATE TABLE t (...) CLUSTER BY (k), ALTER TABLE t CLUSTER BY (k) |
| Copy | CREATE TABLE c SHALLOW CLONE t, ... DEEP CLONE t |
| Change feed | ALTER TABLE t SET TBLPROPERTIES (delta.enableChangeDataFeed = true) then table_changes('t', 2) |
| Info | DESCRIBE DETAIL t, DESCRIBE EXTENDED t |
from delta.tables import DeltaTable
dt = DeltaTable.forName(spark, "dbx_course.customers")
dt.alias("t").merge(updates.alias("s"), "t.customer_id = s.customer_id") \
.whenMatchedUpdateAll().whenNotMatchedInsertAll().execute()
VACUUMremoves files time travel might need: do not shorten the retention casually- Taught in Modules 6, 8 and 12
Auto Loader Configuration
By the end: recall Auto Loader options.
(spark.readStream.format("cloudFiles")
.option("cloudFiles.format", "json")
.option("cloudFiles.schemaLocation", "/Volumes/main/dbx_course/raw/_schema/orders")
.load("/Volumes/main/dbx_course/raw/landing/orders"))
| Option | Does |
|---|---|
cloudFiles.format |
File format: json, csv, parquet, avro... |
cloudFiles.schemaLocation |
Where the inferred schema is stored |
cloudFiles.inferColumnTypes |
Infer real types (default for JSON/CSV is all strings) |
cloudFiles.schemaHints |
Fix some column types: "quantity INT, order_ts TIMESTAMP" |
cloudFiles.schemaEvolutionMode |
addNewColumns, rescue, failOnNewColumns, none |
cloudFiles.includeExistingFiles |
Process files already there at first start |
cloudFiles.maxFilesPerTrigger |
Limit files per batch |
cloudFiles.useNotifications |
Use cloud notifications instead of listing |
pathGlobFilter |
Only files matching a pattern |
- A new column stops the stream once with
addNewColumns; restart picks it up - Bad values go to
_rescued_datawhen it is enabled - Always set a checkpoint on the write side
- Taught in Module 7
Structured Streaming Options
By the end: recall Structured Streaming options.
| Setting | Values |
|---|---|
| Trigger | availableNow=True (only option on serverless), processingTime="1 minute", once=True (old) |
| Output mode | append, update, complete |
| Checkpoint | .option("checkpointLocation", path): one per stream, never shared |
| Watermark | .withWatermark("event_ts", "10 minutes") |
| Dedup | dropDuplicatesWithinWatermark(["event_id"]) |
| Write to table | .toTable("name") |
| Custom write | .foreachBatch(fn): use for MERGE |
(df.withWatermark("event_ts", "10 minutes")
.groupBy(F.window("event_ts", "5 minutes"), "event_type").count()
.writeStream
.outputMode("append")
.option("checkpointLocation", "/Volumes/main/dbx_course/raw/_cp/by_type")
.trigger(availableNow=True)
.toTable("events_by_type"))
- Changing the query's logic may require a new checkpoint
- Windows with
appendemit a result only after the watermark passes it - Taught in Module 11
Lakeflow Pipeline Syntax
By the end: recall Lakeflow Spark Declarative Pipelines syntax.
| Task | Python (from pyspark import pipelines as dp) |
SQL |
|---|---|---|
| Streaming table | @dp.table on a streaming read |
CREATE OR REFRESH STREAMING TABLE |
| Materialized view | @dp.materialized_view |
CREATE MATERIALIZED VIEW |
| Temporary view | @dp.temporary_view |
CREATE TEMPORARY VIEW |
| Expect (log) | @dp.expect("name", "cond") |
CONSTRAINT n EXPECT (cond) |
| Expect (drop) | @dp.expect_or_drop(...) |
... ON VIOLATION DROP ROW |
| Expect (fail) | @dp.expect_or_fail(...) |
... ON VIOLATION FAIL UPDATE |
| Read a stream | spark.readStream.table("t") |
FROM STREAM(t) |
| CDC | dp.create_auto_cdc_flow(...) |
CREATE FLOW f AS AUTO CDC INTO ... |
from pyspark import pipelines as dp
from pyspark.sql import functions as F
@dp.table(comment="Clean orders")
@dp.expect_or_drop("positive_qty", "quantity > 0")
def orders_clean():
return spark.readStream.table("orders_bronze").withColumn("status", F.lower("status"))
CREATE OR REFRESH STREAMING TABLE orders_bronze
AS SELECT * FROM STREAM read_files('/Volumes/main/dbx_course/raw/landing', format => 'json');
- Pipeline code declares tables; the pipeline decides order and refresh
- Free Edition allows one active pipeline at a time
- Taught in Module 9
Unity Catalog SQL Commands
By the end: recall Unity Catalog SQL.
| Task | SQL |
|---|---|
| Objects | CREATE CATALOG c, CREATE SCHEMA c.s, CREATE VOLUME c.s.v |
| Set context | USE CATALOG c, USE SCHEMA c.s |
| Look around | SHOW CATALOGS, SHOW SCHEMAS, SHOW TABLES IN c.s |
| Grant | GRANT SELECT ON TABLE c.s.t TO analysts |
| Revoke | REVOKE SELECT ON TABLE c.s.t FROM analysts |
| Check access | SHOW GRANTS ON TABLE c.s.t |
| Owner | ALTER TABLE c.s.t SET OWNER TO data_eng |
| Docs | COMMENT ON TABLE c.s.t IS '...' |
| Tags | ALTER TABLE c.s.t SET TAGS ('domain' = 'sales') |
| Metadata | DESCRIBE EXTENDED c.s.t, information_schema.tables |
| Row filter | ALTER TABLE t SET ROW FILTER fn ON (col) |
| Column mask | ALTER TABLE t ALTER COLUMN col SET MASK fn |
- Three-level name:
catalog.schema.table - To read a table a user needs
USE CATALOG,USE SCHEMAandSELECT - Grant to groups, not people
- Taught in Modules 6 and 17
Lakeflow Jobs Configuration
By the end: recall Lakeflow Jobs configuration.
| Setting | Options |
|---|---|
| Task types | Notebook, Python script, Python wheel, SQL, pipeline, dbt, job, if/else, for each |
| Dependencies | depends_on; run-if: all succeeded, at least one succeeded, none failed, all done... |
| Parameters | Job-level key/values; read with widgets or argparse |
| Schedule | Quartz cron, e.g. 0 0 6 * * ? + timezone |
| Triggers | Schedule, file arrival, table update, continuous |
| Retries | Per task: count, delay |
| Timeout | Per task or job |
| Concurrency | max_concurrent_runs (default 1), queueing |
| Notifications | Email on start, success, failure |
| Repair / backfill | Rerun failed tasks only; run for past dates |
| Dynamic value | Gives |
|---|---|
{{job.parameters.run_date}} |
A job parameter |
{{job.start_time.iso_date}} |
Date the run started |
{{tasks.ingest.values.rows}} |
A task value from an upstream task |
{{job.run_id}} |
The run id |
- Free Edition: 5 concurrent job tasks per account
- Taught in Module 10 and 27
Performance Tuning Checklist
By the end: run through a performance checklist in order.
| # | Check | Fix |
|---|---|---|
| 1 | Read less data | Filter early, select needed columns, partition or cluster on filter columns |
| 2 | Small files | OPTIMIZE, auto compaction, predictive optimization |
| 3 | Shuffles | Broadcast small side, fewer wide steps |
| 4 | Skew | One slow task: salt the key or rely on adaptive execution |
| 5 | Spill | Too much data per task: more partitions / bigger compute |
| 6 | UDFs | Replace with built-ins or pandas UDF |
| 7 | Collecting | Never collect() or toPandas() a big result |
| 8 | Repeated work | Write an intermediate table (no cache() on serverless) |
| 9 | Wrong table layout | Liquid clustering on the columns you filter by |
| 10 | Plan | Read the query profile: where is the time? |
- Measure first: use See performance or the query profile, not guesses
- Taught in Module 12
Debugging and Troubleshooting
By the end: debug a failing notebook or job in a fixed order.
| Symptom | First check |
|---|---|
AnalysisException: cannot resolve column |
Column name, case, or a renamed column upstream |
Table or view not found |
Catalog and schema (USE), permissions |
PERMISSION_DENIED |
SHOW GRANTS; need USE CATALOG, USE SCHEMA, SELECT |
CAST_INVALID_INPUT |
ANSI mode: bad value. Use try_cast, inspect the row |
DELTA_... concurrent / conflict |
Two writers on the same files: serialise or partition the work |
| Schema mismatch on write | mergeSchema or fix the DataFrame |
| Job slow suddenly | More data? Skew? Query profile |
| Streaming restarts from scratch | Wrong or new checkpoint path |
| Out of memory | collect, huge explode, big broadcast, skewed key |
| Works in notebook, fails in job | Parameters, permissions of the run-as identity, relative paths |
- Narrow with
df.limit(100)anddf.explain() - Check the run-as user: jobs do not run as you unless configured so
- Add logging for row counts between steps
Databricks CLI Commands
By the end: recall Databricks CLI commands.
databricks auth login --host https://<workspace-url> # sign in (OAuth)
databricks current-user me # who am I?
databricks workspace list / # list workspace paths
databricks workspace export /Users/me/nb --format SOURCE
databricks fs ls dbfs:/Volumes/<catalog>/<schema>/<volume>
databricks jobs list
databricks jobs run-now <job-id>
databricks catalogs list
databricks bundle init | validate | deploy -t dev | run <job> -t dev | destroy -t dev
databricks secrets create-scope my_app
databricks --help
- Every command has
--help; add-o jsonfor machine-readable output - Profiles live in
~/.databrickscfg: choose with-p <profile> - Command groups and flags change between CLI versions: check
--help
Free Edition
CLI and token access are not described in the Free Edition docs. Check Settings → Developer in your workspace. See Module 15.
Interview Quick Reference
By the end: answer common interview questions in one line each.
| Question | Short answer |
|---|---|
| What is the lakehouse? | One platform for data lake storage with warehouse features: ACID tables, governance, SQL and ML |
| Delta Lake vs Parquet? | Delta adds a transaction log: ACID, time travel, MERGE, schema enforcement |
| What is Unity Catalog? | Central governance: catalogs, schemas, permissions, lineage, audit |
| Managed vs external table? | Managed: Databricks owns data lifecycle. External: you own the path |
| Transformation vs action? | Transformations are lazy and build a plan; actions run it |
| Narrow vs wide transformation? | Wide ones need a shuffle |
repartition vs coalesce? |
repartition shuffles to any count; coalesce only reduces, no full shuffle |
| What is data skew? | A few keys hold most rows, so a few tasks are slow |
| Broadcast join? | Send the small table to every task, avoid a shuffle |
What does OPTIMIZE do? |
Compacts small files (and clusters data) |
What does VACUUM do? |
Deletes files no longer referenced, older than the retention period |
| How do you make a load idempotent? | MERGE on a key or replaceWhere, plus a checkpoint |
Auto Loader vs COPY INTO? |
Auto Loader scales better and evolves schema; both track loaded files |
| Medallion architecture? | Bronze raw, silver cleaned, gold business-ready |
| SCD 1 vs 2? | 1 overwrites; 2 keeps history with validity dates |
| How do you handle late data? | Watermarks in streaming; reprocess partitions in batch |
| How do you handle bad records? | Quarantine table and expectations, never silently drop |
| Job vs pipeline? | A job orchestrates tasks; a pipeline declares tables and runs them in dependency order |
| How do you promote to production? | Git, bundles, CI tests, deploy by tag, a service principal as run-as |
| How do you control cost? | Serverless/auto-stop, right-sized compute, tags, budgets, fewer full refreshes |
- Explain why along with what: interviewers follow the reasoning
- Have one real project from Module 23 ready to describe: data, design choices, a failure you fixed
What you can do now
- Seventeen sheets: workspace, magics, functions, DataFrames, joins, windows, Delta, ingestion, streaming, pipelines, Unity Catalog, jobs, performance, debugging, CLI, interview
- Check syntax against the docs when versions matter