Trigger, Indizes, Stored Procedures

Einführung

Stell dir vor, du verwaltest einen Online-Shop: Jeden Tag werden neue Bestellungen aufgegeben, Kundendaten geändert und Lagerbestände angepasst. Was passiert aber, wenn jemand aus Versehen ein negatives Gehalt einträgt, eine Bestellung den Bestand ins Minus drückt oder eine Abfrage Millionen von Datensätzen durchsucht, obwohl nur wenige wirklich relevant sind?

Genau hier kommen drei Werkzeuge der relationalen Datenbanken ins Spiel:

  • Trigger
  • Indizes
  • Stored Procedures

In dieser Lerneinheit lernst du, wie diese drei Konzepte funktionieren, wie du sie korrekt einsetzt und wie sie zusammenspielen, um Datenqualität, Performance und Wartbarkeit sicherzustellen.

Lernziele

Nach dieser Lerneinheit kannst du:

  • erklären, was Trigger sind, ihre Ereignisse (INSERT, UPDATE, DELETE) und Zeitpunkte (BEFORE, AFTER) unterscheiden und typische Anwendungsfälle benennen.
  • den Zweck von Indizes beschreiben, Indextypen (B‑Baum, Hash) unterscheiden und Einsatzkriterien für effiziente Abfragen anwenden.
  • Stored Procedures erstellen und aufrufen, dabei die Parameterarten (IN, OUT, INOUT) korrekt einsetzen und deren Nutzen erklären.
  • das Zusammenspiel von Triggern, Indizes und Stored Procedures anhand eines kleinen Beispiels nachvollziehen und deren Beitrag zu Datenqualität und Performance begründen.

Überleitung

Du lernst, was Trigger und Indizes sind, wann du sie einsetzt und wie du sie korrekt implementierst. Der Fokus liegt auf MySQL/MariaDB, die Konzepte gelten aber für andere relationale Systeme ähnlich.

Trigger – Definition, Ereignisse, Zeitpunkte

Ein Trigger ist ein Datenbankobjekt, das bei einem bestimmten Ereignis auf einer Tabelle automatisch ausgeführt wird. Damit setzt du Geschäftsregeln durch, protokollierst Änderungen oder validierst Daten an einer zentralen Stelle.

Auslösende Ereignisse und Ausführungszeitpunkte:

  • Ereignisse: INSERT, UPDATE, DELETE auf einer Tabelle.
  • Zeitpunkte: BEFORE (vor der Operation) und AFTER (nach der Operation).

Diese Unterscheidung bestimmt, ob du eingehende Daten noch verändern/ablehnen darfst (BEFORE) oder auf bereits erfolgte Änderungen reagierst (AFTER). So planst du Logik korrekt ein.

Typische Anwendungsfälle

Du nutzt Trigger für Änderungsprotokolle, automatische Bestandsführung und Validierungen. Die folgenden Beispiele zeigen erprobte Muster in MySQL-Syntax.

Änderungsprotokoll (Audit Log)

-- Protokolliert Namensänderungen in der Tabelle `kunden`
DELIMITER $$
CREATE TRIGGER trg_kunden_audit
AFTER UPDATE ON kunden
FOR EACH ROW
BEGIN
  -- Nur protokollieren, wenn sich der Name tatsächlich geändert hat
  IF (OLD.name <> NEW.name) THEN
    INSERT INTO aenderungslog (
      kunden_id, geaendert_am, alter_name, neuer_name
    ) VALUES (
      NEW.id, NOW(), OLD.name, NEW.name
    );
  END IF;
END$$
DELIMITER ;
  • Ereignis: UPDATE auf kunden.
  • Zeitpunkt: AFTER – ideal, um Konsequenzen zu ziehen (Log schreiben), nachdem die Daten feststehen.
  • Warum nicht BEFORE? Weil du im Log den finalen Zustand dokumentieren willst. AFTER garantiert, dass die Änderung erfolgreich war (sonst würde die Transaktion rollen und der Logeintrag würde ebenfalls zurückgerollt).

Der Trigger läuft nach jedem Update auf kunden und schreibt relevante Änderungen in aenderungslog. Die Bedingung verhindert unnötige Logeinträge und reduziert Storage sowie Lärmsignale.

Automatische Bestandsreduzierung

-- Verringert den Lagerbestand nach dem Anlegen einer Bestellposition
DELIMITER $$
CREATE TRIGGER trg_bestand_nach_bestellposition
AFTER INSERT ON bestellpositionen
FOR EACH ROW
BEGIN
  UPDATE artikel
     SET lagerbestand = lagerbestand - NEW.menge
   WHERE id = NEW.artikel_id;
END$$
DELIMITER ;
  • AFTER ist passend, weil erst nach erfolgreichem Einfügen klar ist, welche Menge tatsächlich gebucht wurde.
  • Ergänze optional eine Validierung (z. B. Bestand darf nicht negativ werden). Das gehört eher in einen BEFORE‑Trigger oder in einen CHECK‑Constraint, um unzulässige Zustände rechtzeitig zu verhindern.

Der Trigger reagiert nach dem Einfügen einer Bestellposition und passt den Bestand des verknüpften Artikels an. So bleibt der Bestand konsistent, unabhängig von der aufrufenden Anwendung.

Datenvalidierung (Ablehnen ungültiger Werte)

-- Verhindert negative Gehälter durch Abbruch mit Fehlermeldung
DELIMITER $$
CREATE TRIGGER trg_gehalt_pruefen
BEFORE UPDATE ON mitarbeiter
FOR EACH ROW
BEGIN
  IF NEW.gehalt < 0 THEN
    SIGNAL SQLSTATE '45000'
      SET MESSAGE_TEXT = 'Gehalt darf nicht negativ sein';
  END IF;
END$$
DELIMITER ;
  • BEFORE eignet sich für Validierung/Normalisierung, weil du Daten korrigieren oder blockieren kannst. Für Logging und Weiterverarbeitung ist AFTER besser geeignet.

Der BEFORE-Trigger bricht die Operation mit einer sprechenden Fehlermeldung ab. So stellst du Datenqualität sicher, bevor fehlerhafte Datensätze geschrieben werden.

Best Practices und Risiken

Halte Trigger klein und zielgerichtet, damit sie die Latenz von DML-Operationen nicht unnötig erhöhen. Dokumentiere Zweck, betroffene Tabellen und Seiteneffekte im Schema oder in separaten Richtlinien.

Empfehlungen:

  • Idempotenz bedenken: Mehrfachauslösungen vermeiden oder korrekt behandeln.
  • Transparenz schaffen: Trigger logisch benennen (trg_<tabelle>_<zweck>), Quellcode versionieren.
  • Seiteneffekte minimieren: Keine komplexen Cross-Table-Kaskaden ohne Notwendigkeit.
  • Fehlerkommunikation: Mit SIGNAL klare Fehlermeldungen liefern; keine stillen Abbrüche.

So bleiben Trigger wartbar und verursachen in Transaktionen keine Überraschungen. Prüfe regelmäßig, ob Logik in gespeicherte Prozeduren oder Anwendungslogik verlagert werden sollte.

Textbasiertes Ablaufdiagramm (INSERT mit AFTER-Trigger)

Client -> DB: INSERT INTO bestellpositionen (...)
DB -> Engine: DML ausführen
Engine -> Constraints: FK/Checks prüfen
Engine -> Table: Row schreiben
Engine -> Trigger: AFTER INSERT auslösen
Trigger -> artikel: UPDATE lagerbestand = lagerbestand - NEW.menge
Engine -> Client: Erfolg/Fehler zurückgeben

Das Diagramm zeigt die Reihenfolge bei einem INSERT mit AFTER-Trigger. Plane Fehlerbehandlung so, dass Triggerfehler die gesamte Transaktion konsistent zurückrollen.

Indizes (Indexe) – Definition, Typen, Einsatz

Ein Index beschleunigt Abfragen, indem er Suchpfade strukturiert und Volltabellenscans reduziert. Er kostet Speicher und Wartungsaufwand bei INSERT/UPDATE/DELETE, daher planst du ihn gezielt.

Wichtige Indextypen

Die Wahl des Typs beeinflusst Operator-Unterstützung, Speicherbedarf und Eignung für Abfrageprofile. In MySQL sind B-Bäume Standard; Hash-Indizes existieren u. a. in Memory-Engines.

IndextypEignungUnterstützte OperatorenStärkenGrenzen
B‑Baum (Standard)Gleichheit und Bereiche=, >, <, BETWEEN, Präfix bei LIKEGut für Sortierung, Range-ScansWeniger effizient bei sehr niedriger Selektivität
HashReine Gleichheit=Sehr schnelle Key‑LookupsKeine Range-Scans, abhängig von Engine

Die Tabelle dient als Orientierung bei der Auslegung deiner Abfragen und Datenverteilungen. Prüfe immer die reale Selektivität und Workloads im System.

Einzelspaltenindex auf Suchspalte

Einzelspaltenindex auf Suchspalte

-- Beschleunigt Suchen nach E-Mail-Adressen
CREATE INDEX idx_kunden_email ON kunden (email);
 
-- Beispielabfrage
SELECT *
  FROM kunden
 WHERE email = "max@beispiel.de";
  • Einzelspaltenindizes sind ideal für Punktabfragen (=). Bei hoher Selektivität (viele unterschiedliche E-Mails) ist der Nutzen besonders groß.

Der Index auf email reduziert die Suchkosten von einem Scan auf einen zielgerichteten Lookup. Das ist besonders wirksam bei hoher Kardinalität und häufigen Punktabfragen.

Zusammengesetzter Index für kombinierte Filter

Zusammengesetzter Index für kombinierte Filter

-- Optimiert typische Filter auf Datum und Status
CREATE INDEX idx_bestellungen_datum_status
  ON bestellungen (bestelldatum, status);
 
-- Passende Abfrage
SELECT *
  FROM bestellungen
 WHERE bestelldatum >= "2024-01-01"
   AND status = "offen"
 ORDER BY bestelldatum;

Was passiert hier? Der zusammengesetzte Index passt exakt zum Filtermuster (erst Datum, dann Status) und deckt zusätzlich die Sortierung nach bestelldatum ab.

Bezug zu Indizes: Dank Leftmost-Prefix-Regel nutzt die DB den Index, wenn die Abfrage mit der linken Indexspalte beginnt. Reihenfolge im Index ist daher entscheidend.

Fachwörter:

  • Leftmost-Prefix: Ein Mehrspaltenindex wird nur genutzt, wenn die Filter links von rechts übereinstimmen (hier: bestelldatum ist der Einstieg).
  • Range-Scan (Bereichsscan): Der Index wird über einen Wertebereich durchlaufen (z. B. bestelldatum >= “2024-01-01”). Das ist viel schneller als ein Vollscan, weil nur der relevante Abschnitt gelesen wird.

Fremdschlüssel-Index für JOINs

Fremdschlüssel-Index für JOINs

-- Beschleunigt JOINs zwischen Bestellungen und Kunden
CREATE INDEX idx_bestellungen_kunde_id
  ON bestellungen (kunde_id);
 
-- Beispiel-JOIN
SELECT b.*
  FROM bestellungen b
  JOIN kunden k ON k.id = b.kunde_id
 WHERE k.status = "aktiv";

Warum ist das schneller?

  • Für jede gefundene kunden.id kann die DB über idx_bestellungen_kunde_id die passenden bestellungen direkt adressieren (statt in bestellungen zu scannen).
  • Das reduziert I/O und Lock-Haltezeiten bei DELETE/UPDATE mit Fremdschlüsselprüfung.

Bezug zu Indizes: Fremdschlüsselspalten sollten fast immer indiziert werden, weil sie Join-Schlüssel und Referenzprüfungen beschleunigen.

Einsatzkriterien und Anti‑Pattern

Setze Indizes für häufige Filter (WHERE), JOIN-Schlüssel und Sortierspalten (ORDER BY). Meide Indizes auf Spalten mit sehr wenigen unterschiedlichen Werten oder selten genutzten Filtern.

Kriterien “verwenden”:

  • Hohe Selektivität und häufige Filterbedingungen.
  • JOIN-Schlüssel und referenzierte Fremdschlüssel.
  • Sortierreihenfolgen, die du stabil halten willst.

Kriterien “vermeiden”:

  • Sehr niedrige Kardinalität (z. B. boolesche Flags ohne weitere Filter).
  • Tabellen mit extrem hohem DML‑Aufkommen ohne Abfragevorteil.
  • Redundante Überindizierung ohne messbaren Nutzen.

Diese Leitlinien verhindern, dass Wartungskosten die gewonnenen Lesevorteile übersteigen. Prüfe jede Entscheidung mit Messdaten aus deiner Umgebung.

Performanceanalyse und Faustregeln

Nutze Abfragepläne und Messwerte, um Indexwirksamkeit zu prüfen. Eine grobe Daumenregel: Ein Index lohnt sich oft, wenn eine Abfrage weniger als etwa 10-15 % der Zeilen zurückgibt.

-- Abfrageplan anzeigen (MySQL)
EXPLAIN SELECT *
  FROM kunden
 WHERE email = "test@example.com";

EXPLAIN zeigt, ob ein Index verwendet wird, welche Zugriffsart greift und wie viele Zeilen geschätzt werden. Interpretiere die Ausgabe im Kontext realer Laufzeiten und ergänzender Metriken.

⏳ Lädt Dataview-Inhalt...

Was sind Stored Procedures?

Eine Stored Procedure ist eine in der Datenbank gespeicherte Folge von SQL-Anweisungen (inkl. Variablen, Bedingungen, Schleifen), die du mit CALL ... aufrufst.

Sie ähnelt einer Funktion/Prozedur in Programmiersprachen: Parameter rein, Logik ausführen, Ergebnis(e) zurückgeben.

Vorteile auf einen Blick

  • Performance: Parser/Optimizer-Arbeit wird wiederverwendet; weniger Round-Trips zwischen Anwendung und DB.
  • Wiederverwendbarkeit: Einmal implementieren, an vielen Stellen konsistent nutzen.
  • Sicherheit: Zentralisierte Geschäftslogik; weniger Risiko für SQL-Injection bei konsequenter Parametrisierung.
  • Weniger Netzwerkverkehr: Mehr Logik “nah an den Daten”.

Parameterarten verstehen (IN, OUT, INOUT)

  • IN: Wert wird hineingegeben, in der Procedure nicht verändert.
  • OUT: Wert wird von der Procedure zurückgegeben (wird innerhalb der SP gesetzt).
  • INOUT: Kombination - Wert kommt rein, kann geändert und geändert zurückgegeben werden.

Merke: OUT/INOUT erfordern Variablen beim Aufruf (z. B. Session-Variablen oder benannte Variablen im Client).

Einfache Stored Procedure (ohne Parameter)

-- Listet alle aktiven Kunden
DELIMITER $$
CREATE PROCEDURE GetAllKunden()
BEGIN
  SELECT kunde_id, name, email
    FROM kunden
   WHERE aktiv = 1;
END$$
DELIMITER ;
 
-- Aufruf
CALL GetAllKunden();
  • DELIMITER $$ / DELIMITER ; – ändert temporär das Befehlstrennzeichen, damit das ; innerhalb der Procedure erlaubt ist.
  • CREATE PROCEDURE … BEGIN … END – definiert die SP.
  • SELECT … FROM kunden WHERE aktiv = 1 – die eigentliche Abfrage.

Stored Procedure mit IN‑Parameter

-- Liefert einen Kunden anhand der ID (nur Lesezugriff)
DELIMITER $$
CREATE PROCEDURE sp_GetKundeById(IN p_kunde_id INT)
BEGIN
  SELECT kunde_id, name, email, aktiv
    FROM kunden
   WHERE kunde_id = p_kunde_id;
END$$
DELIMITER ;
 
-- Aufruf (gibt ein Resultset zurück)
CALL sp_GetKundeById(123);

Erläuterung

  • IN p_kunde_id ist ein Eingabeparameter: Der Wert wird beim Aufruf übergeben und innerhalb der SP nur gelesen, nicht verändert.
  • Die Procedure gibt direkt ein Resultset zurück (vergleichbar mit einer normalen SELECT‑Abfrage).
  • Typischer Einsatz: gezieltes Abfragen einzelner Datensätze oder gefilterte Ergebnisse.

Diese Procedure nimmt eine Kundennummer als Eingabe (IN) entgegen. Sie sucht den entsprechenden Datensatz in der Tabelle und gibt die Kundendetails als Resultset zurück. IN-Parameter sind schreibgeschützt – sie dienen nur zum Filtern oder Steuern.

Stored Procedure mit OUT‑Parameter

-- Gibt die Anzahl aktiver Kunden über OUT-Parameter zurück
DELIMITER $$
CREATE PROCEDURE sp_CountAktiveKunden(OUT p_anzahl INT)
BEGIN
  SELECT COUNT(*)
    INTO p_anzahl
    FROM kunden
   WHERE aktiv = 1;
END$$
DELIMITER ;
 
-- Aufruf und Ergebnisabholung (Session-Variablen verwenden)
SET @anz = NULL;
CALL sp_CountAktiveKunden(@anz);
SELECT @anz AS aktive_kunden;

Erläuterung

  • OUT p_anzahl ist ein Ausgabeparameter: Die Procedure schreibt den Wert hinein und gibt ihn zurück.
  • Im Aufruf muss eine Variable übergeben werden (z. B. @anz), die nach Ausführung gefüllt ist.
  • Typischer Einsatz: Kennzahlen, Statuswerte oder Berechnungen, die nicht als Tabellen-Resultset zurückgegeben werden sollen.

Diese Procedure hat keinen Eingabewert, sondern schreibt ihr Ergebnis in einen OUT-Parameter. Der Aufrufer stellt eine Variable bereit (z. B. @anz), die nach Ausführung die Anzahl aktiver Kunden enthält. So lassen sich einzelne Kennzahlen direkt an die Anwendung zurückgeben.

Stored Procedure mit INOUT‑Parameter

-- Erhöht den Kundenrabatt relativ und gibt den neuen Wert über INOUT zurück
DELIMITER $$
CREATE PROCEDURE sp_UpdateRabatt(
  IN  p_kunde_id INT,
  INOUT p_rabatt  DECIMAL(5,2)  -- z. B. 5.00 = 5 Prozent
)
BEGIN
  DECLARE v_alt DECIMAL(5,2);
  DECLARE v_neu DECIMAL(5,2);
 
  -- aktuellen Rabatt lesen
  SELECT rabatt INTO v_alt
    FROM kunden
   WHERE kunde_id = p_kunde_id;
 
  -- neuen Rabatt berechnen: alter + p_rabatt (Delta)
  SET v_neu = v_alt + p_rabatt;
 
  -- Update durchführen
  UPDATE kunden
     SET rabatt = v_neu,
         geaendert_am = NOW()
   WHERE kunde_id = p_kunde_id;
 
  -- neuen Wert an den Aufrufer zurückgeben
  SET p_rabatt = v_neu;
END$$
DELIMITER ;
 
-- Aufruf: p_rabatt kommt hinein als "Delta" und geht hinaus als neuer Rabatt
SET @delta := 2.50;    -- wir möchten +2.50 Prozentpunkte addieren
CALL sp_UpdateRabatt(123, @delta);
SELECT @delta AS neuer_rabatt_prozent;

Erläuterung

  • INOUT kombiniert beide Richtungen: Der Wert wird als Eingabe genutzt (hier: Erhöhung/Delta) und nach der Berechnung als Ausgabe zurückgegeben.

Diese Procedure kombiniert Eingabe und Ausgabe in einem INOUT-Parameter. Beim Aufruf übergibt der Nutzer zuerst einen Wert (hier: eine geplante Erhöhung von 2,50). Die Procedure liest den aktuellen Rabatt aus der Tabelle, addiert den übergebenen Wert und speichert das Ergebnis.

Anschließend wird der INOUT-Parameter mit dem neuen Endwert überschrieben, sodass der Aufrufer sofort sieht, welcher Rabatt jetzt für den Kunden gilt. INOUT ist somit hilfreich, wenn ein Wert sowohl verarbeitet als auch aktualisiert zurückgegeben werden soll, ohne einen zusätzlichen OUT-Parameter zu benötigen.

OUT mit mehreren Werten

-- Liefert mehrere Kennzahlen via OUT-Parameter
DELIMITER $$
CREATE PROCEDURE sp_KundenKPIs(
  OUT p_anzahl_aktiv INT,
  OUT p_anzahl_neu   INT,
  OUT p_anzahl_inaktiv INT
)
BEGIN
  SELECT SUM(aktiv = 1),
         SUM(aktiv = 1 AND erstellt_am >= CURDATE() - INTERVAL 30 DAY),
         SUM(aktiv = 0)
    INTO p_anzahl_aktiv, p_anzahl_neu, p_anzahl_inaktiv
    FROM kunden;
END$$
DELIMITER ;
 
-- Aufruf
SET @a:=NULL, @n:=NULL, @i:=NULL;
CALL sp_KundenKPIs(@a, @n, @i);
SELECT @a AS aktiv, @n AS neu_30t, @i AS inaktiv;

Erläuterung
Hier zeigt sich, dass eine Procedure mehrere OUT-Parameter gleichzeitig befüllen kann. Sie berechnet verschiedene Kennzahlen (aktiv, neu, inaktiv) in einem Durchgang. Dadurch spart man sich mehrere Abfragen und erhält die Werte kompakt zurück.

Zusammenspiel: Stored Procedures × Indizes × Trigger

-- Aktualisiert Kundendaten und löst dabei Trigger aus
DELIMITER $$
CREATE PROCEDURE KundeAktualisieren(
  IN p_kunde_id INT,
  IN p_neuer_name VARCHAR(100)
)
BEGIN
  UPDATE kunden
     SET name = p_neuer_name,
         geaendert_am = NOW()
   WHERE kunde_id = p_kunde_id;
  -- Ein AFTER UPDATE-Trigger auf `kunden` kann die Änderung z. B. ins Audit-Log schreiben.
END$$
DELIMITER ;

Wie greift alles ineinander?

  • Index: kunden(kunde_id) sorgt für schnellen Key‑Lookup im UPDATE.
  • Trigger: AFTER UPDATE auf kunden protokolliert Änderungen (Audit). So bleibt die SP schlank; das Protokollieren ist „entkoppelt“ im Trigger.
  • Transaktionalität: Wenn das UPDATE fehlschlägt, feuert auch kein Trigger; bei Fehlern in Triggern rollt die gesamte Transaktion zurück.

Best Practices

Trigger

  • So einfach und schnell wie möglich halten; keine unnötigen Nebenwirkungen.
  • Rekursion vermeiden (Trigger, die weitere Trigger in Kaskaden feuern).
  • Gut dokumentieren und versionieren; klar benennen (trg_<tabelle>_<ereignis>_<zweck>).
  • Gründlich testen (Happy‑Path, Fehlerpfad, konkurrierende Updates).

Best Practices

Indizes

  • Indexnutzung überwachen (EXPLAIN, Laufzeiten, Handler‑Metriken).
  • Überindizierung vermeiden; ungenutzte/duplizierte Indizes entfernen.
  • Reihenfolge bei Mehrspaltenindizes am realen Filter/SORT ausrichten (Leftmost‑Prefix).
  • DML‑Kosten im Blick behalten (INSERT/UPDATE/DELETE werden durch Indizes teurer).

Best Practices

Stored Procedures

  • Sprechende Namen und klare Parameter.
  • Robuste Fehlerbehandlung (SIGNAL, Fehlercodes, saubere Rollbacks).
  • Transaktionen dort kapseln, wo Teilschritte atomar sein müssen.
  • Set‑basierte Lösungen bevorzugen; Cursor nur, wenn nötig.
  • Eingaben validieren; Kantenfälle testen (NULL, Leerstrings, Grenzwerte).
⏳ Lädt Dataview-Inhalt...

Zusammenfassung

Zusammenfassung:

1. Trigger

Definition: Trigger sind Datenbankobjekte, die bei bestimmten Ereignissen (INSERT, UPDATE, DELETE) automatisch ausgeführt werden. Sie wirken wie „Wächter“, die Geschäftsregeln durchsetzen oder Änderungen protokollieren.

Zeitpunkte:

  • BEFORE – vor der eigentlichen Änderung, gut für Validierungen.
  • AFTER – nach der Änderung, gut für Logging oder Folgeschritte.

Typische Anwendungsfälle:

  • Audit/Protokoll: Änderungen in Logtabellen speichern.
  • Automatische Aktionen: Bestandsreduktion nach Bestellung.
  • Validierung: Ungültige Werte (z. B. negatives Gehalt) abfangen.

Best Practices:

  • Trigger einfach halten, keine komplexe Logik.
  • Klar benennen (trg_<tabelle>_<ereignis>).
  • Seiteneffekte vermeiden und dokumentieren.

2. Indizes

Definition: Indizes sind Strukturen, die den Zugriff auf Daten beschleunigen, ähnlich wie ein Stichwortverzeichnis in einem Buch. Statt eine ganze Tabelle zu durchsuchen, wird über den Index direkt gesprungen.

Arten:

  • B-Baum (Standard): Unterstützt Gleichheit und Bereichsabfragen.
  • Hash: Sehr schnell für exakte Vergleiche, keine Bereichsabfragen.

Einsatzbereiche:

  • Spalten in WHERE-Bedingungen.
  • JOIN-Schlüssel (Fremdschlüssel).
  • Sortierungen (ORDER BY).

Best Practices:

  • Indizes nur für häufig genutzte Filter anlegen.
  • Selektivität beachten: je vielfältiger die Werte, desto nützlicher.
  • Überflüssige/ungenutzte Indizes regelmäßig entfernen.

Fachbegriffe:

  • Range-Scan: Lesen eines Teilbereichs im Index (z. B. Datum von X bis Y).
  • Volltabellenscan: Alle Zeilen werden gelesen, da kein Index genutzt wird.
  • Selektivität: Anteil der gefilterten Zeilen an allen Zeilen (je kleiner, desto besser für Indizes).

3. Stored Procedures (SPs)

Definition: In der Datenbank gespeicherte Programme (SQL-Sequenzen), die mit CALL ausgeführt werden. Sie können Parameter entgegennehmen und Werte zurückgeben.

Parameterarten:

  • IN: Eingabe, nicht veränderbar.
  • OUT: Ausgabe, wird in der SP gesetzt.
  • INOUT: Kombination – Wert kommt rein, wird verändert zurückgegeben.

Beispiele:

  • IN: Einen Kunden anhand der ID abrufen.
  • OUT: Anzahl aktiver Kunden zählen und zurückgeben.
  • INOUT: Rabatt erhöhen und den neuen Wert an den Aufrufer zurückgeben.
  • Mehrere OUTs: Mehrere Kennzahlen (KPIs) in einer Abfrage liefern.

Best Practices:

  • SPs mit sprechenden Namen versehen.
  • Fehler klar behandeln (SIGNAL SQLSTATE).
  • Transaktionen nutzen, wenn mehrere Schritte atomar sein müssen.
  • Möglichst set-basiert arbeiten, Cursor nur wenn nötig.