Data Engineering

External Tables in Databricks: Patterns und Pitfalls

Was Data Engineers über External Tables in Databricks wissen müssen — wann statt Managed Tables, Storage Credentials, Partition-Sync und die kritischen Pitfalls.

Harbinger Team3. April 20269 Min. LesezeitAktualisiert 14.5.2026
  • databricks
  • external-tables
  • unity-catalog
  • delta-lake
  • data-engineering
Inhaltsverzeichnis29 Abschnitte

TL;DR: External Tables in Databricks koppeln Metadaten und Daten — DROP TABLE löscht nicht die Files. Nutze sie für Multi-System-Access (S3+Athena+Trino), externe Lifecycle-Pflege und Data-Residency. Bevorzuge Delta-Format (erspart Partition-Sync). Storage-Credentials und External Locations in Unity Catalog erzwingen.

External Tables sind eines der nützlichsten — und am häufigsten missverstandenen — Features in Databricks. Richtig eingesetzt geben sie dir flexible Data Governance, Multi-System-Zugriff und feingranulare Storage-Kontrolle. Nachlässig eingesetzt produzieren sie Orphaned Data, Security-Lücken und Governance-Albträume.

Dieser Guide deckt alles ab: wann External statt Managed, korrekte Konfiguration mit Unity Catalog, Partition-Management und die Pitfalls, die auch erfahrene Teams erwischen.


Managed vs External Tables: Die Kernunterscheidung

Bevor wir tief in External Tables einsteigen, lohnt es sich, präzise zu sein, was sie von Managed Tables unterscheidet — die Implikationen sind erheblich.

DimensionManaged TableExternal Table
Daten-OrtDatabricks-managed StorageDu gibst den Ort an
DROP TABLE-VerhaltenLöscht Daten UND MetadatenLöscht NUR Metadaten
Storage-LifecycleAn die Tabelle gekoppeltUnabhängig von der Tabelle
Unity-Catalog-SupportVollVoll (mit Storage Credentials)
PerformanceGleichGleich
Delta-SupportJaJa
Cross-System-ZugriffNur über DatabricksJedes Tool mit Storage-Access

Der kritische Unterschied: DROP TABLE auf einer External Table löscht deine Daten nicht. Das ist Feature und Falle zugleich.


Wann External Tables nutzen?

External Tables sind die richtige Wahl, wenn:

  1. Daten außerhalb Databricks entstehen — z. B. eine App, die Parquet direkt nach S3/ADLS schreibt
  2. Multi-System-Access nötig ist — dieselben Daten von Databricks, Athena, BigQuery Omni, Trino etc. gelesen
  3. Storage-Lifecycle extern gemanagt wird — S3-Lifecycle-Policies oder Azure-Data-Lake-Tiering pflegen Retention
  4. Regulierte Daten-Residency — Daten müssen in einem bestimmten Account/Region/Bucket bleiben (DSGVO, EU-Hosting)
  5. Migrations-Szenarien — du registrierst einen bestehenden Data Lake in Unity Catalog ohne Files zu bewegen

Wenn du den vollen Lifecycle kontrollierst und nur Databricks die Daten liest, sind Managed Tables einfacher und sicherer.


External Tables in Unity Catalog erstellen

Unity Catalog verlangt explizite Storage Credentials und External Locations, bevor du eine External Table erstellen kannst. Das ist by Design — verhindert Ad-hoc-Zugriff auf beliebige Storage-Pfade.

Schritt 1: Storage Credential erstellen

-- Create a storage credential (AWS IAM role example)
CREATE STORAGE CREDENTIAL my_s3_credential
  WITH (
    aws_iam_role = 'arn:aws:iam::123456789012:role/databricks-storage-role'
  )
  COMMENT 'Credential for data lake S3 bucket';
# Via CLI
databricks storage-credentials create \
  --name my_s3_credential \
  --aws-iam-role arn:aws:iam::123456789012:role/databricks-storage-role

Schritt 2: External Location erstellen

-- Register an S3 path as an allowed external location
CREATE EXTERNAL LOCATION my_data_lake
  URL 's3://my-company-datalake/prod/'
  WITH (STORAGE CREDENTIAL my_s3_credential)
  COMMENT 'Production data lake root';

-- Validate the location is accessible
DESCRIBE EXTERNAL LOCATION my_data_lake;

Schritt 3: External Table erstellen

-- Create an external Delta table
CREATE TABLE catalog.schema.events
  (
    event_id    STRING,
    user_id     STRING,
    event_type  STRING,
    event_ts    TIMESTAMP,
    country     STRING,
    revenue_usd DOUBLE
  )
  USING DELTA
  LOCATION 's3://my-company-datalake/prod/events/'
  COMMENT 'User events — external Delta table';
# PySpark equivalent
spark.sql("""
    CREATE TABLE IF NOT EXISTS catalog.schema.events
    USING DELTA
    LOCATION 's3://my-company-datalake/prod/events/'
    COMMENT 'User events — external Delta table'
""")

Mit Non-Delta-External-Tables arbeiten

Nicht alle External Tables sind Delta. Du wirst oft Parquet, CSV oder JSON registrieren, das von externen Systemen produziert wurde:

-- External Parquet table (partitioned)
CREATE TABLE catalog.schema.raw_events
  USING PARQUET
  PARTITIONED BY (year INT, month INT, day INT)
  LOCATION 's3://my-company-datalake/raw/events/'
  OPTIONS (
    'compression' = 'snappy',
    'mergeSchema' = 'true'
  );

-- After creating a partitioned external table, sync partitions
MSCK REPAIR TABLE catalog.schema.raw_events;
-- External CSV table with explicit schema (always prefer this over inferSchema)
CREATE TABLE catalog.schema.raw_uploads
  (
    upload_id   STRING,
    user_id     STRING,
    file_name   STRING,
    uploaded_at TIMESTAMP,
    size_bytes  LONG
  )
  USING CSV
  OPTIONS (
    'header' = 'true',
    'sep' = ',',
    'multiline' = 'true'
  )
  LOCATION 's3://my-company-datalake/uploads/';

Warnung: inferSchema = 'true' liest alle Files, um Typen zu inferieren. Auf großen Datasets teuer und produziert brüchige Schemas. In Produktion immer Schemas explizit definieren.


Partition-Management: Der häufigste Schmerz

Partitionierte External Tables brauchen explizites Partition-Management. Hier rennen die meisten Teams in Schwierigkeiten.

Das Problem

Wenn neue Partitionen im externen Storage entstehen (z. B. ein neues date=2024-01-15/-Directory in S3), entdeckt Databricks sie nicht automatisch für Non-Delta-Tabellen.

# New files landed in S3:
# s3://bucket/events/date=2024-01-15/*.parquet

# This query returns NO results — partition not registered yet
spark.sql("SELECT * FROM catalog.schema.events WHERE date = '2024-01-15'").show()

Lösung 1: MSCK REPAIR TABLE (voller Sync)

-- Sync all partitions — discovers new AND removes deleted
MSCK REPAIR TABLE catalog.schema.events;

Einfach, aber teuer auf großen Tabellen — scannt den gesamten Storage-Pfad.

Lösung 2: ADD PARTITION (inkrementell)

-- Add a single partition explicitly (fast)
ALTER TABLE catalog.schema.events
  ADD IF NOT EXISTS PARTITION (date = '2024-01-15')
  LOCATION 's3://bucket/events/date=2024-01-15/';
# Automate with PySpark for daily partitions
from datetime import date

def register_partition(table: str, partition_date: date, base_path: str):
    date_str = partition_date.strftime("%Y-%m-%d")
    path = f"{base_path}/date={date_str}/"
    spark.sql(f"""
        ALTER TABLE {table}
        ADD IF NOT EXISTS PARTITION (date = '{date_str}')
        LOCATION '{path}'
    """)
    print(f"Registered partition: {date_str}")

register_partition(
    table="catalog.schema.events",
    partition_date=date.today(),
    base_path="s3://bucket/events"
)

Lösung 3: Delta External Tables (Best Practice)

Die beste Lösung: Delta-Format für External Tables nutzen. Delta pflegt seinen eigenen Transaction-Log, Partitionen sind immer in Sync — kein MSCK REPAIR nötig.

-- Convert an existing Parquet external table to Delta
CONVERT TO DELTA catalog.schema.events
  PARTITIONED BY (date STRING);

Kritische Pitfalls

Pitfall 1: DROP TABLE löscht nichts

Das gefährlichste Missverständnis über External Tables: DROP TABLE entfernt nur die Databricks-Metadaten-Registrierung. Die zugrundeliegenden Files werden nicht angerührt.

-- This does NOT delete any data in S3/ADLS
DROP TABLE catalog.schema.events;

-- After this, the data still exists at 's3://bucket/events/'
-- But it is now invisible to Databricks (unregistered)
-- You must re-CREATE TABLE or face ghost data accumulation

Risiko: Teams droppen und re-erstellen External Tables bei Schema-Migrationen und akkumulieren Orphaned Data im Storage, das nie aufgeräumt wird.

Praxis: Pflege ein Register externer Tabellenpfade. Vor dem Drop bestätigen, ob der Storage manuell aufgeräumt werden soll.

Pitfall 2: Mehrere Tabellen zeigen auf dieselbe Location

-- This is valid SQL but creates a dangerous situation
CREATE TABLE catalog.schema.events_v1 LOCATION 's3://bucket/events/';
CREATE TABLE catalog.schema.events_v2 LOCATION 's3://bucket/events/';

-- Writes to events_v1 will appear in events_v2 queries and vice versa
-- Schema enforcement is bypassed between the two table definitions

Unity Catalog verhindert das standardmäßig nicht. Audit deine External Locations regelmäßig auf Überlappung.

Pitfall 3: Schema-Evolution ohne Tabellen-Update

Wenn die zugrundeliegenden Files neue Spalten gewinnen, aktualisiert sich das registrierte Tabellen-Schema nicht automatisch (für Non-Delta):

# New Parquet files have an extra column "referrer_url"
# But the table schema does not know about it yet

df = spark.table("catalog.schema.raw_events")
df.printSchema()  # "referrer_url" is missing

# Fix: use mergeSchema option when reading directly
df = (
    spark.read
    .option("mergeSchema", "true")
    .format("parquet")
    .load("s3://bucket/raw/events/")
)

Für Delta-External-Tables wird Schema-Evolution via delta.columnMapping und ALTER TABLE gehandhabt:

ALTER TABLE catalog.schema.events ADD COLUMNS (referrer_url STRING);

Pitfall 4: External-Table-Security und Over-Permissioning

External Tables umgehen Row-/Column-Level-Security, wenn der zugrundeliegende Storage direkt zugänglich ist. Ein User mit S3-Zugriff, aber ohne Unity-Catalog-Permission, kann die Daten trotzdem lesen, indem er Databricks umgeht.

Das Exposure-Modell:

Unity Catalog erzwingt RLS/CLS
  -> External Table -> S3-Bucket
                          ^
        User mit direktem S3-Access umgeht alle Kontrollen

Lösung: Storage Credentials sperren. Die IAM-Rolle oder Managed Identity, die vom Storage Credential genutzt wird, sollte das einzige Principal mit Read-Access auf den Bucket-Pfad sein. Einzelne User erreichen die Daten nur über Databricks.

Pitfall 5: REFRESH TABLE nach externen Updates vergessen

Wenn Files außerhalb Databricks ergänzt, entfernt oder geändert werden, kann der Metadaten-Cache veraltet sein:

-- Force metadata refresh after external file changes
REFRESH TABLE catalog.schema.events;

-- For partitioned tables, target a specific partition
REFRESH TABLE catalog.schema.events PARTITION (date = '2024-01-15');

Pitfall 6: Auto-Optimize auf External Locations

Auto Optimize (Optimized Writes + Auto Compaction) wird auf Tabellen-Ebene aktiviert. Für External Delta Tables musst du sicherstellen, dass das Storage Credential Write-Permissions hat — sonst failt der OPTIMIZE-Schritt still:

-- Verify the credential has write access
VALIDATE STORAGE CREDENTIAL my_s3_credential
  WITH (READ_WRITE) LOCATION 's3://bucket/events/';

Best-Practices-Übersicht

PraxisWarum
Delta-Format für External Tables bevorzugenEliminiert Partition-Sync-Schmerz
Schemas explizit definieren — nie inferSchemaReproduzierbar, performant
Unity-Catalog-External-Locations nutzenZentralisierte Access-Control
Niemals External-Table-Locations überlappenVerhindert Daten-Integritäts-Probleme
External Locations regelmäßig auditierenOrphaned Data finden, bevor sie kosten
Storage auf IAM-/RBAC-Ebene sperrenSecurity endet nicht bei Databricks
DROP TABLE-Verhalten in Runbooks dokumentierenTeams droppen versehentlich Tabellen
Storage Credentials nach Erstellung validierenFehlkonfiguration früh fangen

External-Table-Registrierung automatisieren

Wenn du viele External Tables managst, registrierst du konsistent automatisiert:

# external_table_registry.py
from dataclasses import dataclass, field

@dataclass
class ExternalTable:
    catalog: str
    schema_name: str
    name: str
    location: str
    fmt: str = "DELTA"
    partition_cols: list = field(default_factory=list)

def register_external_table(tbl: ExternalTable):
    fqn = f"{tbl.catalog}.{tbl.schema_name}.{tbl.name}"
    partition_clause = ""
    if tbl.partition_cols:
        cols = ", ".join(tbl.partition_cols)
        partition_clause = f"PARTITIONED BY ({cols})"

    spark.sql(f"""
        CREATE TABLE IF NOT EXISTS {fqn}
        USING {tbl.fmt}
        {partition_clause}
        LOCATION '{tbl.location}'
    """)
    print(f"Registered: {fqn} -> {tbl.location}")

tables = [
    ExternalTable("prod", "raw",    "events",  "s3://bucket/raw/events/"),
    ExternalTable("prod", "raw",    "users",   "s3://bucket/raw/users/"),
    ExternalTable("prod", "silver", "events",  "s3://bucket/silver/events/"),
]

for t in tables:
    register_external_table(t)

External Locations auf Orphaned Data prüfen

Periodisch auditieren, um Daten zu finden, die von keiner Tabelle mehr referenziert werden:

# audit_external_locations.py
from databricks.sdk import WorkspaceClient

w = WorkspaceClient()

# List all registered external tables and their locations
registered_locations = set()
for table in w.tables.list(catalog_name="prod", schema_name="raw"):
    if table.table_type.value == "EXTERNAL" and table.storage_location:
        registered_locations.add(table.storage_location.rstrip("/"))

print(f"Registered external locations: {len(registered_locations)}")
for loc in sorted(registered_locations):
    print(f"  {loc}")

# Cross-reference with your known storage paths to find orphans
# (requires cloud storage SDK for your provider)

FAQ

Sollte ich Managed oder External Tables wählen?

Default: Managed. Nur External, wenn du explizit Multi-System-Access, externen Lifecycle oder Daten-Residency brauchst. Managed ist sicherer (Drop löscht alles), External ist flexibler.

Wie verhindere ich Orphaned Data?

Drei Praktiken: (1) ein Register aller External-Locations pflegen, (2) DROP TABLE in Runbooks dokumentieren — manuelle Storage-Cleanup als Folgeschritt, (3) quartalsweise Audit-Lauf gegen die Cloud-Storage-Listing-API.

Funktionieren External Tables DSGVO-konform?

Ja — External Tables sind sogar das richtige Pattern, wenn EU-Daten-Residency erforderlich ist (Bucket im EU-Region pinnen). Lösch-Anfragen (Right-to-be-Forgotten) müssen aber an der Datenquelle umgesetzt werden, nicht nur via DROP TABLE.

Was kostet eine External Delta Table mehr/weniger als eine Managed?

Storage-Kosten identisch (gleiche Cloud-Bucket-Tarife). Compute-Kosten identisch. Operativer Overhead höher bei External (Storage-Credentials, External-Locations, Audit).

Kann ich Managed -> External konvertieren?

Nicht direkt. Workaround: External-Tabelle mit CREATE TABLE AS SELECT an gewünschter Location anlegen, dann die Managed droppen. Während der Migration Schema-Konstanz prüfen.


Schluss

External Tables sind ein mächtiges Werkzeug im Databricks-Ökosystem — aber sie verlangen mehr Disziplin als Managed Tables. Die Entkopplung von Metadaten und Daten ist absichtlich, sie erzeugt aber Angriffsfläche für Fehler: Orphaned Data, veraltete Partitionen, Security-Lücken, Schema-Drift.

Die Teams, die External Tables erfolgreich nutzen, pflegen klare Dokumentation, was wo registriert ist, automatisieren Partition-Sync und Location-Auditing und erzwingen strikte Storage-Level-Access-Controls neben Unity-Catalog-Permissions.

Den Überblick über alle External-Table-Registrierungen, ihre Locations, Last-Refresh und Überlappungen zu behalten — das ist genau die operative Sichtbarkeit, die Harbinger Explorer über deinen Databricks-Workspace hinweg bietet.


Stand: 14. Mai 2026.

H

Geschrieben von

Harbinger Team

Cloud-, Data- und AI-Engineer in DACH. Schreibt seit 2018 über infrastruktur­kritische Tech-Entscheidungen — keine Marketing- Folien, sondern echte Trade-offs aus Production-Workloads.

Hat dir das geholfen?

Jede Woche ein neuer Artikel über DACH-Cloud, Data und AI — direkt in dein Postfach. Kein Spam, kein Marketing-Sprech.

Kein Spam. 1-Klick-Abmeldung. Datenschutz bei Loops.so.