Magento EAV-Schema: Performance-Grenzen und Umgehungen
AI generated
InnoDB
SQL
MySQL · Magento · Datenbankdesign · Performance
Magento EAV-Schema: Performance-Grenzen und Umgehungen
warum Produktabfragen so viele Joins brauchen

Das EAV-Schema erlaubt Magento beliebig viele Produktattribute ohne ALTER TABLE, erkauft das aber mit Join-Aufwand bei jeder Produktabfrage. Wer die Tabellenstruktur aus entity-, attribute- und typspezifischen value-Tabellen versteht, kann echte Engpässe von vermeintlichen EAV-Problemen unterscheiden und gezielt mit Flat-Tables oder eigenen Index-Tabellen gegensteuern.

18 Min. Lesezeit EAV-Schema · Joins · Flat-Table · Indexierung Magento 2.4.x · MySQL 8 / MariaDB 10.6

1. Was das EAV-Schema in Magento eigentlich ist

Das EAV-Schema (Entity-Attribute-Value) ist die Antwort von Magento auf ein Problem, das jedes flexible Produktkatalogsystem hat: Ein Schrauben-Shop braucht Gewinde und Länge als Attribute, ein Mode-Shop braucht Größe und Material, ein Elektronik-Shop braucht Wattzahl und Spannung. Ein klassisches relationales Schema mit fester Spaltenanzahl pro Tabelle würde für jeden neuen Attributtyp ein ALTER TABLE erfordern, was bei großen Tabellen mit Millionen Zeilen zu langen Sperrzeiten führt. Das EAV-Schema umgeht das, indem es Attribute als Zeilen statt als Spalten modelliert, die Struktur wird dynamisch statt statisch.

Der Kompromiss dieser Flexibilität ist strukturell eingebaut: Jedes Attribut eines Produkts liegt in einer eigenen Zeile einer separaten Tabelle, getrennt nach Datentyp. Wo eine klassische Tabelle mit fester Spaltenzahl eine Produktzeile mit 40 Spalten hätte, verteilt das EAV-Schema dieselben 40 Attribute auf mehrere Tabellen mit jeweils jeweils einer Zeile pro Attribut und Produkt. Das ist der Grund, warum eine einzelne Produktabfrage in Magento intern zu einer zweistelligen Anzahl von JOIN-Operationen führen kann, wenn sie naiv implementiert wird. Wer die Mechanik des EAV-Schemas nicht kennt, sieht in einem Slow-Query-Log oft nur die Symptome, nicht die Ursache.

Wichtig für die Einordnung: Das EAV-Schema ist kein Magento-Sonderweg, sondern ein bekanntes Datenbankmuster, das auch in anderen Systemen mit dynamischen Attributen vorkommt. Magento nutzt es konsequent für Produkte, Kategorien und Kunden. Die Herausforderung ist nicht, das EAV-Schema zu vermeiden, sondern seine Kostenstruktur zu verstehen und gezielt dort abzufedern, wo sie tatsächlich zum Problem wird.

2. Tabellenstruktur: entity, attribute und typspezifische value-Tabellen

Im Zentrum des EAV-Schemas für Produkte steht catalog_product_entity. Diese Tabelle enthält nur die Basisdaten: entity_id, sku, attribute_set_id, type_id und Zeitstempel. Alle eigentlichen Attributwerte wie Name, Preis, Beschreibung oder Farbe liegen nicht hier, sondern in separaten Tabellen, die nach Datentyp aufgeteilt sind: catalog_product_entity_varchar für kurze Texte, catalog_product_entity_int für Ganzzahlen und Select-Attribute, catalog_product_entity_decimal für Preise und Gewichte, catalog_product_entity_text für lange Beschreibungen und catalog_product_entity_datetime für Datumsfelder.

Jede dieser Tabellen hat dieselbe Grundstruktur: value_id, attribute_id, store_id, entity_id und value. Die Tabelle eav_attribute definiert, welches Attribut (zum Beispiel "color" oder "weight") welche attribute_id hat und in welcher Tabelle sein Wert liegt, gesteuert über die Spalte backend_type. Die store_id-Spalte ermöglicht Store-View-spezifische Überschreibungen, ein Attribut wie der Produktname kann für store_id = 0 (Default) einen Wert haben und für store_id = 2 einen abweichenden, übersetzten Wert.

Diese Aufteilung ist kein Zufall, sondern eine bewusste Normalisierung nach Datentyp. Ohne sie müsste jede value-Tabelle Spalten für alle möglichen Typen vorhalten und mit NULL-Werten arbeiten, was bei MySQL zu ineffizienter Speichernutzung und schlechterer Indexpflege führt. Das EAV-Schema in Magento erkauft sich dadurch eine sauberere Typisierung auf Kosten von mehr Tabellen, die bei jeder vollständigen Produktabfrage beteiligt sind.


-- Structure of the varchar value table (same pattern for int, decimal, text, datetime)
DESCRIBE catalog_product_entity_varchar;
-- +----------------+------------------+------+-----+---------+----------------+
-- | Field          | Type             | Null | Key | Default | Extra          |
-- +----------------+------------------+------+-----+---------+----------------+
-- | value_id       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
-- | attribute_id   | smallint unsigned| NO   | MUL | 0       |                |
-- | store_id       | smallint unsigned| NO   | MUL | 0       |                |
-- | entity_id      | int(10) unsigned | NO   | MUL | 0       |                |
-- | value          | varchar(255)     | NULL |     | NULL    |                |
-- +----------------+------------------+------+-----+---------+----------------+

-- Unique constraint prevents duplicate attribute values per entity and store
SHOW INDEX FROM catalog_product_entity_varchar WHERE Key_name = 'UNQ_KEY';

-- Find the attribute_id and backend_type for a given attribute code
SELECT attribute_id, attribute_code, backend_type, frontend_input
FROM eav_attribute
WHERE entity_type_id = 4 AND attribute_code = 'color';

3. Der Join-Kostenfaktor bei einer einzelnen Produktabfrage

Der praktische Effekt des EAV-Schemas zeigt sich, sobald man versucht, ein vollständiges Produkt mit mehreren Attributen in einer einzigen SQL-Abfrage zu laden. Für jedes Attribut, das aus einer anderen value-Tabelle stammt, braucht die Abfrage einen eigenen LEFT JOIN. Ein Produkt mit Name, Beschreibung, Preis, Gewicht und einem Farb-Select-Attribut benötigt bereits fünf Joins gegen bis zu vier verschiedene value-Tabellen, plus den Join gegen catalog_product_entity selbst. In der Praxis liegen typische Attribute-Sets bei 30 bis 80 Attributen, wovon aber nur ein Teil in einer konkreten Ansicht (Produktliste, Detailseite, API-Response) tatsächlich benötigt wird.

Magentos eigener ORM-Layer (Model/ResourceModel) kapselt diese Joins über Magento\Eav\Model\Entity\AbstractEntity und lädt Attribute standardmäßig nicht alle auf einmal, sondern nur die im Attribute-Set als "used in product listing" oder explizit angeforderten. Trotzdem bleibt der Join-Kostenfaktor des EAV-Schemas real: Bei einer Kategorieseite mit 60 Produkten und 10 relevanten Attributen pro Produkt kann eine naive Implementierung schnell mehrere hundert Joins pro Seitenaufruf erzeugen, wenn kein Caching und keine Index-Tabelle zwischengeschaltet ist.

Genau deshalb nutzt Magento für Kategorie- und Suchseiten nicht das rohe EAV-Schema, sondern die Indexer-Tabellen wie catalog_product_index_price, die Preisdaten bereits vorberechnet und flach vorhalten. Das EAV-Schema bleibt die Quelle der Wahrheit für Admin-Bearbeitung und Produktdetailseiten, während lesehäufige, performancekritische Pfade auf denormalisierte Index-Strukturen ausweichen. Wer diesen Unterschied nicht kennt, optimiert oft an der falschen Stelle.


-- Loading five attributes for one product requires five joins against EAV value tables
SELECT
  e.entity_id,
  e.sku,
  name_val.value    AS name,
  desc_val.value    AS description,
  price_val.value   AS price,
  weight_val.value  AS weight,
  color_val.value   AS color_option_id
FROM catalog_product_entity e
LEFT JOIN catalog_product_entity_varchar name_val
  ON name_val.entity_id = e.entity_id AND name_val.attribute_id = 73 AND name_val.store_id = 0
LEFT JOIN catalog_product_entity_text desc_val
  ON desc_val.entity_id = e.entity_id AND desc_val.attribute_id = 75 AND desc_val.store_id = 0
LEFT JOIN catalog_product_entity_decimal price_val
  ON price_val.entity_id = e.entity_id AND price_val.attribute_id = 77 AND price_val.store_id = 0
LEFT JOIN catalog_product_entity_decimal weight_val
  ON weight_val.entity_id = e.entity_id AND weight_val.attribute_id = 82 AND weight_val.store_id = 0
LEFT JOIN catalog_product_entity_int color_val
  ON color_val.entity_id = e.entity_id AND color_val.attribute_id = 93 AND color_val.store_id = 0
WHERE e.entity_id = 4521;

4. Attribute-Sets und ihre Wirkung auf Kardinalität

Attribute-Sets bestimmen, welche Attribute für eine Gruppe von Produkten überhaupt relevant sind, gesteuert über eav_attribute_set und eav_attribute_group. In der Theorie sollte ein schlankes Attribute-Set die Join-Last des EAV-Schemas reduzieren, weil weniger Attribute geladen werden müssen. In der Praxis wachsen Attribute-Sets über Jahre unkontrolliert, weil neue Attribute für Marketing-Zwecke, Filterfacetten oder Feed-Exporte hinzugefügt werden, ohne alte, nicht mehr genutzte Attribute zu entfernen.

Ein Shop mit 150 Attributen pro Set, von denen tatsächlich nur 40 auf der Produktdetailseite und 15 in der Produktliste angezeigt werden, trägt unnötigen EAV-Overhead in jeder Admin-Speicherung und jedem Reindex mit. Jedes zusätzliche Attribut im EAV-Schema bedeutet eine zusätzliche Zeile pro Produkt und Store-View in der jeweiligen value-Tabelle, was sich bei 50.000 Produkten und 3 Store-Views schnell zu Millionen Zeilen allein in catalog_product_entity_varchar aufsummiert. Eine regelmäßige Attribut-Bereinigung ist deshalb keine Kosmetik, sondern direkte EAV-Performance-Arbeit.

5. Flat-Table-Alternativen: catalog_product_flat

Magento bietet seit Langem eine Flat-Table-Option (catalog_product_flat_1, wobei die Zahl die Store-ID ist) als Alternative zum reinen EAV-Schema. Die Flat-Table denormalisiert alle relevanten Attribute in eine einzige breite Tabelle mit einer Spalte pro Attribut, ähnlich einem klassischen relationalen Produktkatalog. Das eliminiert die Join-Kosten des EAV-Schemas vollständig für Lesezugriffe, weil ein einzelnes SELECT ohne Joins alle Attributwerte liefert.

Der Preis dieser Vereinfachung ist der Reindex-Aufwand: Jede Änderung an einem Produkt oder Attribut erfordert einen Rebuild der Flat-Tabelle, der bei großen Katalogen mehrere Minuten bis Stunden dauern kann und Sperrzeiten für die Tabelle bedeutet. Seit Magento 2.3 wird die Flat-Table-Option offiziell nicht mehr empfohlen und in neueren Versionen zunehmend als Legacy-Feature behandelt, weil moderne Suchindizes (Elasticsearch/OpenSearch) und die Preisindex-Tabellen dieselbe Denormalisierung für die relevanten Anwendungsfälle bereits übernehmen. Für Individualentwicklungen mit sehr spezifischen, lesehäufigen Abfragen außerhalb von Kategorie- und Suchseiten kann eine eigene, schlanke Flat-Tabelle trotzdem sinnvoller sein als das vollständige EAV-Schema zu befragen.

6. Wann das EAV-Schema wirklich der Flaschenhals ist

Bevor man das EAV-Schema für eine Performance-Regression verantwortlich macht, braucht es Messdaten statt Vermutung. Der erste Schritt ist das MySQL Slow Query Log mit einem niedrigen long_query_time-Schwellenwert, kombiniert mit EXPLAIN auf den identifizierten Queries. Zeigt EXPLAIN bei einer Produktabfrage viele rows in Kombination mit Using temporary oder Using filesort bei den EAV-value-Joins, ist das ein klares Signal, dass die Join-Kette des EAV-Schemas tatsächlich der begrenzende Faktor ist.

Ein zweites Diagnosewerkzeug ist der Performance Schema von MySQL, mit dem sich die kumulierte Zeit pro Tabelle und Query-Digest auswerten lässt. Erst wenn catalog_product_entity_varchar oder catalog_product_entity_int konsistent unter den Top-Tabellen nach kumulierter Lesezeit auftauchen, lohnt sich der Aufwand einer strukturellen EAV-Optimierung. Häufig zeigt die Messung stattdessen, dass ein fehlender Index auf einer ganz anderen Tabelle oder eine ineffiziente PHP-seitige Collection-Iteration die eigentliche Ursache ist, nicht das EAV-Schema selbst.


-- Enable slow query logging for EAV diagnosis
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;

-- Inspect cumulative time per table via performance_schema
SELECT object_name, count_read, sum_timer_read/1000000000 AS read_time_ms
FROM performance_schema.table_io_waits_summary_by_table
WHERE object_schema = 'magento'
  AND object_name LIKE 'catalog_product_entity%'
ORDER BY sum_timer_read DESC
LIMIT 10;

-- EXPLAIN a typical multi-join EAV query
EXPLAIN SELECT e.entity_id, v.value
FROM catalog_product_entity e
LEFT JOIN catalog_product_entity_varchar v
  ON v.entity_id = e.entity_id AND v.attribute_id = 73 AND v.store_id = 0
WHERE e.attribute_set_id = 4;

7. Red Herring: falsche Verdächtige statt EAV-Schema

Ein sehr häufiges Muster in der Praxis: Ein Shop wird langsamer, jemand sieht viele Tabellen mit dem Präfix catalog_product_entity_ im Slow Log und schließt vorschnell, dass das EAV-Schema generell abgeschafft werden muss. Tatsächlich liegt die Ursache oft woanders. N+1-Ladeprobleme in eigenem PHP-Code, bei denen eine Collection pro Produkt einzeln nachgeladen wird statt Attribute gebündelt zu laden, erzeugen dieselben Symptome wie ein ineffizientes EAV-Schema, sind aber ein Anwendungscode-Problem.

Ebenso häufig sind fehlende oder falsch gesetzte Indizes auf attribute_id, store_id und entity_id in Kombination, die MySQL zu einem Full-Table-Scan zwingen, obwohl die Tabellenstruktur des EAV-Schemas an sich korrekt indiziert wäre. Auch ein fehlender oder falsch konfigurierter Full-Page-Cache und Redis-Objekt-Cache führt dazu, dass EAV-Queries bei jedem Request neu ausgeführt werden, obwohl sie sich kaum ändern. In all diesen Fällen wäre eine Migration weg vom EAV-Schema Zeitverschwendung, weil das eigentliche Problem bestehen bliebe.

8. Praxis-Patterns gegen EAV-Overhead

Statt das komplette EAV-Schema zu ersetzen, haben sich gezielte Patterns bewährt. Erstens: Attribute-Sets regelmäßig auditieren und ungenutzte Attribute per bin/magento-Skript oder direkt über eav_attribute entfernen, inklusive der zugehörigen Werte in den value-Tabellen. Zweitens: Für sehr lesehäufige, aber selten geänderte Datenpunkte eine eigene, schmale Index-Tabelle bauen, die per Observer bei Produktänderung aktualisiert wird, statt bei jedem Request das volle EAV-Schema zu befragen.

Drittens: Collections gezielt mit addAttributeToSelect() nur für tatsächlich benötigte Attribute füllen statt addAttributeToSelect('*'), das lädt sonst reflexartig alle Attribute des Sets und multipliziert die Join-Anzahl unnötig. Viertens: Bei API-lastigen Integrationen (GraphQL, REST) einen dedizierten Read-Layer mit eigener, denormalisierter Tabelle einführen, der asynchron aus dem EAV-Schema gespeist wird, statt synchron bei jedem API-Call zu joinen.


-- Custom slim index table fed by an observer instead of joining the full EAV schema
CREATE TABLE catalog_product_feed_index (
  entity_id INT UNSIGNED NOT NULL,
  sku VARCHAR(64) NOT NULL,
  price DECIMAL(12,4) NOT NULL,
  color_label VARCHAR(64) NULL,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (entity_id),
  KEY IDX_PRICE (price)
) ENGINE=InnoDB;

-- Populated asynchronously (e.g. catalog_product_save_after observer) instead of
-- reading catalog_product_entity_* on every request
INSERT INTO catalog_product_feed_index (entity_id, sku, price, color_label)
SELECT e.entity_id, e.sku, price_val.value, color_opt.value
FROM catalog_product_entity e
LEFT JOIN catalog_product_entity_decimal price_val
  ON price_val.entity_id = e.entity_id AND price_val.attribute_id = 77 AND price_val.store_id = 0
LEFT JOIN eav_attribute_option_value color_opt
  ON color_opt.option_id = 3 AND color_opt.store_id = 0
WHERE e.entity_id = 4521
ON DUPLICATE KEY UPDATE price = VALUES(price), color_label = VALUES(color_label);

9. DB-seitiges Tuning für EAV-Tabellen

Auch ohne Architekturänderung lässt sich das EAV-Schema auf reiner MySQL-Ebene tunen. Der zusammengesetzte Unique-Index aus entity_id, attribute_id und store_id, den Magento standardmäßig auf allen value-Tabellen anlegt, sollte in dieser Reihenfolge auch für die häufigsten Query-Muster passen. Bei eigenen Reports, die viele Produkte nach einem bestimmten Attributwert filtern, lohnt sich ein zusätzlicher Index mit attribute_id und value als führenden Spalten, weil MySQL sonst über entity_id scannen muss.

Der InnoDB Buffer Pool sollte groß genug dimensioniert sein, um die am häufigsten gelesenen value-Tabellen weitgehend im Speicher zu halten, denn Disk-I/O ist bei EAV-Joins mit vielen kleinen Zeilen ein größerer Faktor als bei wenigen breiten Zeilen. Ein Blick auf innodb_buffer_pool_size im Verhältnis zur Gesamtgröße von catalog_product_entity_* zeigt schnell, ob der Puffer für den Katalog ausreicht. Zuletzt hilft regelmäßiges ANALYZE TABLE auf den EAV-Tabellen, damit der Query-Optimizer aktuelle Kardinalitätsschätzungen für Join-Reihenfolgen hat, gerade nach großen Import- oder Reindex-Läufen, die die Datenverteilung des EAV-Schemas verändern.


-- Extra covering index for attribute-value lookups outside the default query pattern
ALTER TABLE catalog_product_entity_int
  ADD INDEX IDX_ATTR_VALUE (attribute_id, value);

-- Refresh optimizer statistics after large imports or reindex runs
ANALYZE TABLE catalog_product_entity_varchar, catalog_product_entity_int,
              catalog_product_entity_decimal, catalog_product_entity_text;

-- Check InnoDB buffer pool sizing against EAV table footprint
SELECT table_name, ROUND((data_length + index_length) / 1024 / 1024, 1) AS size_mb
FROM information_schema.TABLES
WHERE table_schema = 'magento' AND table_name LIKE 'catalog_product_entity%'
ORDER BY size_mb DESC;

Vergleich: EAV-Schema, Flat-Table und Custom Index-Tabelle

Aspekt EAV-Schema Flat-Table Custom Index-Tabelle
Schreibaufwand Gering, nur betroffene Attribute Hoch, kompletter Reindex nötig Gering, Update per Observer
Leseaufwand Hoch, viele Joins pro Attribut Sehr gering, ein SELECT Sehr gering, gezielter Zuschnitt
Flexibilität neuer Attribute Sehr hoch, kein ALTER TABLE Gering, Spaltenwechsel nötig Mittel, bewusst begrenzt
Wartungsstatus in Magento Aktiv, Kern-Architektur Legacy, nicht empfohlen Eigenverantwortlich zu pflegen
Typischer Einsatz Admin, Produktdetail Historisch, Altsysteme API, Feed, Reporting

Mironsoft

Magento-Datenbankarchitektur und Performance-Audits

EAV-Schema als Performance-Bremse in eurem Shop?

Wir messen mit Slow Query Log und Performance Schema, ob das EAV-Schema wirklich die Ursache ist, und bauen bei Bedarf gezielte Index-Tabellen statt eine pauschale Architekturmigration vorzuschlagen.

EAV-Audit

Attribute-Sets und Query-Muster gegen echte Slow-Log-Daten prüfen

Index-Tabellen

Schlanke, observer-gepflegte Tabellen für lesehäufige Pfade

Query-Tuning

Indizes, Buffer Pool und ANALYZE TABLE auf die Kataloggröße abstimmen

10. Zusammenfassung

Das EAV-Schema ist eine bewusste Architekturentscheidung von Magento, um beliebige Produktattribute ohne strukturelle Schemaänderungen zu ermöglichen. Der Preis dafür sind Join-Kosten bei jeder vollständigen Produktabfrage, weil Attribute typspezifisch auf mehrere value-Tabellen wie catalog_product_entity_varchar, _int, _decimal, _text und _datetime verteilt sind. Für lesehäufige, performancekritische Pfade wie Kategorie- und Suchseiten weicht Magento bereits selbst auf denormalisierte Indexer-Tabellen aus, das EAV-Schema bleibt die Quelle der Wahrheit im Admin und auf der Produktdetailseite.

Bevor man das EAV-Schema als Ursache einer Performance-Regression identifiziert, braucht es Messdaten aus Slow Query Log und Performance Schema statt Vermutung, denn N+1-Ladeprobleme, fehlende Indizes und ein schwacher Cache erzeugen dieselben Symptome. Wo das EAV-Schema tatsächlich der Flaschenhals ist, helfen ein Attribute-Set-Audit, gezielte Custom-Index-Tabellen und MySQL-seitiges Tuning von Indizes und Buffer Pool deutlich mehr als eine pauschale Migration zu Flat-Tables.

Magento EAV-Schema: Das Wichtigste auf einen Blick

Tabellenstruktur

catalog_product_entity plus typspezifische value-Tabellen für varchar, int, decimal, text und datetime.

Join-Kosten

Jedes Attribut aus einer anderen value-Tabelle bedeutet einen zusätzlichen JOIN pro Produktabfrage.

Flat-Table

Denormalisierte Alternative, seit Magento 2.3 nicht mehr empfohlen wegen Reindex-Aufwand.

Diagnose

Slow Query Log und performance_schema.table_io_waits_summary_by_table vor jeder Architekturentscheidung.

11. FAQ: Magento EAV-Schema

1Was bedeutet EAV-Schema konkret?
Entity-Attribute-Value: Attribute als Zeilen in typspezifischen value-Tabellen statt als feste Spalten, verknüpft über entity_id und attribute_id.
2Warum langsamer als klassische Tabellen?
Jedes Attribut aus einer separaten value-Tabelle bedeutet einen zusätzlichen JOIN pro vollständiger Produktabfrage.
3Flat-Tables als Ersatz sinnvoll?
Seit 2.3 nicht mehr empfohlen wegen Reindex-Aufwand. Indexer-Tabellen und Suchindizes decken die kritischen Pfade bereits ab.
4Welche Tabellen gehören dazu?
catalog_product_entity plus _varchar, _int, _decimal, _text, _datetime sowie eav_attribute für Metadaten.
5Wie messe ich den echten Flaschenhals?
Slow Query Log, EXPLAIN und performance_schema.table_io_waits_summary_by_table statt Vermutung.
6Was sind typische falsche Verdächtige?
N+1-Ladeprobleme, fehlende Indizes und ein schwacher Object- oder Full-Page-Cache erzeugen dieselben Symptome.
7EAV-Overhead ohne Architekturwechsel senken?
Attribute-Sets auditieren, addAttributeToSelect() gezielt statt mit Stern nutzen, eigene schmale Index-Tabellen per Observer.
8Rolle des InnoDB Buffer Pool?
Viele kleine Zeilen machen Disk-I/O relevanter. Ausreichender Buffer Pool hält häufig gelesene value-Tabellen im Speicher.
9Warum keine EAV-Joins auf Kategorieseiten?
Zu hohe Join-Last bei vielen Produkten pro Seite. Vorberechnete Indexer-Tabellen wie catalog_product_index_price übernehmen das.
10Wozu ANALYZE TABLE bei EAV-Tabellen?
Aktualisiert Kardinalitätsschätzungen für die Join-Reihenfolge, wichtig nach großen Importen oder Reindex-Läufen.