Spalten zusammenfügen


In diesem Abschnitt geht es um eine Verschleierung, die vor allem bei mehrspaltigen Indizes auftritt.

Das erste Beispiel hat wieder mit Datums-Typen zu tun, steht aber vor dem umgekehrten Problem als zuvor. Die MySQL-Abfrage fügt getrennte Datums- und Zeit-Spalten zusammen:

SELECT ...
  FROM ...
 WHERE ADDTIME(date_column, time_column)
     > DATE_ADD(now(), INTERVAL -1 DAY)

Damit werden alle Zeilen der letzten 24 Stunden gesucht. Diese Abfrage kann einen zusammengesetzten Index auf (DATE_COLUMN, TIME_COLUMN) aber nicht verwenden, weil die Suche nicht auf den indizierten Spalten, sondern auf abgeleiteten Daten stattfindet.

Bei unseren Schlulungs-, Tuning-, und
Literaturangeboten ist für jeden was dabei

Das Problem kann man vermeiden, indem man einen Daten-Typen wie DATETIME verwendet, der sowohl eine Datums- als auch eine Zeit-Kompo­nen­te hat. Die Abfrage kann sich dann direkt auf diese Spalte beziehen:

SELECT ...
  FROM ...
 WHERE datetime_column
     > DATE_ADD(now(), INTERVAL -1 DAY)

Wenn man vor diesem Problem steht, hat man aber nur in den seltensten Fällen die Möglichkeit die Tabelle umzubauen.

Die nächste Option ist, einen Funktions-basierten Index zu benutzen – wenn die verwendete Datenbank sie anbietet. Das hat natürlich alle Nachteile, die schon zuvor besprochen wurden. Bei diesem Beispiel arbeiten wir aber mit einer MySQL Datenbank – Funktions-basierte Indizierung ist ohnehin keine Option.

Dennoch hat man die Möglichkeit die Abfrage so zu formulieren, dass der zusammengesetzte Index auf DATE_COLUMN und TIME_COLUMN zumindest teilweise mit einem Zugriffsprädikat genutzt werden kann. Dazu muss man eine zusätzliche Bedingung auf DATE_COLUMN in die where-Klausel aufnehmen.

 WHERE ADDTIME(date_column, time_column)
     > DATE_ADD(now(), INTERVAL -1 DAY)
   AND date_column
    >= DATE(DATE_ADD(now(), INTERVAL -1 DAY))

Diese Bedingung ist, aus logischer Sicht, absolut redundant. Sie ist aber direkt auf der ersten Index-Spalte – kann also als Zugriffsprädikat genutzt werden. Diese Methode ist zwar nicht perfekt, aber als Annäherung meist gut genug.

Tipp

Verwende eine redundante Bedingung mit der höchstwertigen Spal­te, wenn eine Bereichs-Bedingung mehrere Spalten zusammen­fügt.

Verwendet bei PostgreSQL die Row-Values-Syntax.

Diese Methode kann man auch anwenden, wenn Datum und Zeit als Text gespeichert sind. Dafür muss eine lexikalische Sortierung allerdings eine chronologische Reihenfolge liefern – wie zum Beispiel von ISO 8601 vorgesehen (YYYY-MM-DD HH:MM:SS). Das folgende Beispiel demonstriert diese Methode mit der TO_CHAR-Funktion der Oracle Datenbank:

SELECT ...
  FROM ...
 WHERE date_string || time_string
     > TO_CHAR(sysdate - 1, 'YYYY-MM-DD HH24:MI:SS')
   AND date_string
    >= TO_CHAR(sysdate - 1, 'YYYY-MM-DD')

Der Problemstellung, mehrere Spalte auf einmal zu vergleichen, werden wir im Abschnitt „Durch Ergebnisse blättern“ nochmal begegnen. Auch dort findet diese Annäherungsmethode Verwendung.

Manchmal muss man Bedingungen gezielt verschleiern, damit sie nicht als Zugriffsprädikat verwendet werden. Wir hatten dieses Problem bereits, als wir die Auswirkungen von Bind-Para­me­tern auf LIKE-Suchen behandelt haben. Dazu folgendes Beispiel:

SELECT last_name, first_name, employee_id
  FROM employees
 WHERE subsidiary_id = ?
   AND last_name LIKE ?

Angenommen es gibt sowohl einen Index auf SUBSIDIARY_ID als auch auf LAST_NAME. Welcher ist für diese Abfrage besser?

Ohne zu wissen, wo die Wildcard-Zeichen im Suchbegriff stehen, kann man keine qualifizierte Antwort geben. Auch die Datenbank kann nur raten. Wenn man aber weiß, dass der Suchbegriff immer mit einem Wildcard-Zeichen beginnt, kann man die entsprechende Bedingung absichtlich verschleiern. Dadurch kann der LIKE-Filter nicht als Zugriffsprädikat verwendet werden:

SELECT last_name, first_name, employee_id
  FROM employees
 WHERE subsidiary_id = ?
   AND last_name || '' LIKE ?

Dafür genügt es, einen leeren String an die Spalte LAST_NAME anzuhängen. Dieses Vorgehen ist allerdings nur der letzte Ausweg, wenn es keine anderen Möglichkeiten mehr gibt.

Wenn dir gefällt, wie ich die Dinge erkläre, wirst du meine Kurse lieben.

Über den Autor

Photo of Markus Winand
Markus Winand stimmt Entwickler auf SQL-Performance ein. Er hat das Buch SQL Performance Explained veröffentlicht und bietet inhouse Schulungen sowie Tuning-Leistungen auf http://winand.at/ an.