{ }
type
GraphQL · Magento · EAV · Performance · Flat-Catalog · Produktabfragen
Magento GraphQL und EAV
Welche Kosten hinter Produktabfragen stecken

Eine Magento GraphQL-Produktabfrage, die einfach aussieht, kann intern dutzende SQL-JOINs über EAV-Tabellen auslösen. Wer nicht versteht, wie das Entity-Attribute-Value-Modell funktioniert, optimiert an der falschen Stelle. Dieser Artikel zeigt, warum EAV teuer ist, welche Maßnahmen helfen und wo die Grenzen liegen.

17 Min. Lesezeit EAV-Tabellen · Flat-Catalog · Attribute-Sets · Index · Caching · Custom Attributes Magento 2.4 · MySQL / MariaDB

1. EAV-Modell in Magento: Grundlagen verstehen

Das Entity-Attribute-Value-Modell (EAV) ist eine Datenbankarchitektur, die Magento für Produkte, Kunden und Kategorien verwendet. Statt alle Attribute in einer breiten Tabelle zu speichern – etwa catalog_product mit hundert Spalten –, speichert EAV jeden Attributwert als eigene Zeile in typisierten Wertetabellen. Der Vorteil: beliebig viele Custom-Attribute können ohne Schema-Änderungen hinzugefügt werden. Der Nachteil: für jedes abgefragte Attribut ist ein JOIN über die entsprechende Wertetabelle nötig.

In der Praxis bedeutet das: Eine Produktliste mit 20 Artikeln, die jeweils 30 Attribute in der GraphQL-Response enthält, kann intern über 600 EAV-Werte aus verschiedenen Tabellen zusammentragen – für jede Attribute-Wertetabelle (varchar, int, decimal, text, datetime) ein separater JOIN. Magento hat für dieses Problem Mechanismen, aber sie funktionieren nur unter bestimmten Voraussetzungen, und viele Projekte nutzen sie nicht vollständig.

2. Welche EAV-Tabellen bei Produktabfragen betroffen sind

Die EAV-Daten für Produkte sind auf fünf typisierte Wertetabellen aufgeteilt: catalog_product_entity_varchar für Texte wie Name und URL-Key, catalog_product_entity_int für ganzzahlige Werte wie Status und Sichtbarkeit, catalog_product_entity_decimal für Dezimalwerte wie Preise und Gewicht, catalog_product_entity_text für lange Texte wie Beschreibungen und catalog_product_entity_datetime für Datumsfelder. Dazu kommt catalog_product_entity als Basistabelle mit den unveränderlichen Identifiers.

Jede dieser Tabellen hat eine Zeile pro Produkt und Attribut, nicht eine Zeile pro Produkt. Wenn ein Produkt 40 Attribute hat und diese auf drei Wertetabellen verteilt sind, entstehen drei JOINs – jeweils über eine Tabelle mit mehreren Millionen Zeilen in großen Katalogen. Ohne geeignete Indizes und ohne materialisierten Flat-Catalog sind diese JOINs die häufigste Ursache für langsame Produktlisten in Magento-GraphQL-Setups.

3. Wie GraphQL-Queries EAV-Abfragen auslösen

Eine GraphQL-Query für Produkte löst in Magento eine Kette von Datenbankoperationen aus. Der Root-Resolver für products führt zunächst eine Suche oder Filterabfrage aus, die die passenden Produkt-IDs liefert. Für jede Produkt-ID werden dann die angeforderten Attribute aus den EAV-Tabellen geladen. Welche Attribute geladen werden, hängt davon ab, welche Felder in der GraphQL-Query angefragt wurden – aber nicht immer ist diese Verbindung direkt: Magento lädt intern manchmal mehr Attribute als vom Frontend explizit angefragt, weil bestimmte Attribute für die interne Verarbeitung (Preisberechnung, Berechtigungsprüfung) immer benötigt werden.

Das bedeutet: auch eine scheinbar schlanke Query mit nur sku und name kann intern mehr EAV-Zugriffe auslösen als erwartet, wenn der Resolver zusätzliche Attribute für Berechtigungsprüfungen oder Store-spezifische Preisinformationen benötigt. Ohne Query-Profiling ist dieser Overhead unsichtbar. Erst ein Blick in das SQL-Query-Log zeigt das vollständige Bild der Datenbankoperationen hinter einer scheinbar einfachen GraphQL-Query.


# This simple-looking query can trigger many EAV table joins internally
# Magento loads not just name/sku but also status, visibility, price data for authorization
query ProductListEAVTest {
  products(
    filter: { category_id: { eq: "10" } }
    pageSize: 20
  ) {
    total_count
    items {
      sku                    # catalog_product_entity (no JOIN needed)
      name                   # catalog_product_entity_varchar JOIN
      url_key                # catalog_product_entity_varchar JOIN
      status                 # catalog_product_entity_int JOIN
      price_range {
        minimum_price {
          final_price { value }   # complex price calculation — multiple tables
        }
      }
      special_price          # catalog_product_entity_decimal JOIN
      news_from_date         # catalog_product_entity_datetime JOIN
      description { html }   # catalog_product_entity_text JOIN
    }
  }
}

4. Flat-Catalog: die wichtigste EAV-Gegenmaßnahme

Der Magento Flat-Catalog ist eine Indexierungsstrategie, die EAV-Daten in materialisierten breiten Tabellen zusammenführt. Statt beim Laden eines Produkts über fünf JOINs Attribute aus EAV-Wertetabellen zu sammeln, enthält catalog_product_flat_1 (für Store 1) alle Attribute als eigene Spalten – ein einfacher SELECT reicht aus. Die Tabelle wird beim Indexieren (bin/magento indexer:reindex catalog_product_flat) aktualisiert und bleibt bis zur nächsten Reindizierung gültig.

Der Flat-Catalog ist standardmäßig nicht aktiviert und muss im Admin unter Stores > Configuration > Catalog > Catalog > Storefront eingeschaltet werden. Nach der Aktivierung muss einmal vollständig reindiziert werden. Der Gewinn ist erheblich: Produktlistenabfragen, die ohne Flat-Catalog dutzende JOINs erzeugen, reduzieren sich auf einen einzigen Table-Scan der Flat-Tabelle. Für Stores mit vielen Custom-Attributen und großen Katalogen ist das oft der größte einzelne Performance-Hebel überhaupt.

5. Custom-Attribute und ihr Einfluss auf die Performance

Jedes Custom-Attribut, das über ein eigenes Modul zum Produkt-Entitätstyp hinzugefügt wird, erhöht die EAV-Komplexität. Wenn ein Attribut dem Flat-Catalog hinzugefügt wird, ist der Overhead minimal – es erscheint als zusätzliche Spalte in der Flat-Tabelle. Wenn ein Attribut nicht im Flat-Catalog ist, erfordert jeder Zugriff einen zusätzlichen JOIN über die EAV-Wertetabelle. Eigene Module müssen deshalb explizit angeben, ob ihre Attribute in den Flat-Catalog aufgenommen werden sollen.

Ein weiteres Problem entsteht bei Attributen mit hoher Kardinalität: Attribut-Sets mit vielen Optionen (z.B. Farbe mit 500 Werten) erzeugen in der catalog_product_entity_int-Tabelle viele Zeilen, deren Auflösung über eav_attribute_option_value wieder ein JOIN ist. Für GraphQL-Responses, die Attribute-Labels statt numerischer IDs zurückgeben, multiplizieren sich diese JOINs weiter. Resolver, die Attribut-Labels für Filteroptionen zurückgeben, sollten deshalb gecachte Lookup-Tabellen verwenden statt bei jedem Request über die Option-Tabellen zu joinen.

6. EAV-Kosten sichtbar machen: Profiling und Logging

Der erste Schritt zur EAV-Optimierung ist das Sichtbarmachen der tatsächlichen Datenbankkosten. Der Magento SQL-Query-Logger zeigt alle SQL-Abfragen eines Requests mit Ausführungszeiten. Für eine GraphQL-Produktlisten-Query sollte man zählen, wie viele der Queries gegen EAV-Tabellen gehen und wie viel Zeit sie zusammen verbrauchen. In einem schlecht konfigurierten Setup sieht man häufig, dass 70–90 % der Request-Zeit in EAV-Tabellen-JOINs verbracht wird.

Für tiefergehende Analyse empfiehlt sich MySQL's EXPLAIN-Befehl für die häufigsten Queries. Ein Query ohne geeigneten Index, der über eine Millionen-Zeilen-EAV-Tabelle scannt, ist sofort an einem type: ALL in der EXPLAIN-Ausgabe erkennbar. Für Magento-Projekte ist es sinnvoll, periodisch einen Query-Profiling-Lauf durchzuführen und die Top-10-teuersten SQL-Queries zu identifizieren – in produktiven Stores kommen diese fast immer aus EAV-Abfragen oder fehlenden Indizes.

7. EAV-Zugriffsstrategien im Vergleich

Es gibt mehrere Strategien, den EAV-Overhead zu reduzieren. Die Wahl der richtigen Strategie hängt von der Größe des Katalogs, der Anzahl der Custom-Attribute und den Anforderungen an Datenaktualität ab.

Strategie Performance-Gewinn Komplexität Einschränkungen
Flat-Catalog aktivieren Sehr hoch Gering Braucht regelmäßige Reindizierung
Attribute zum Flat-Catalog hinzufügen Hoch Mittel Nur bei Standard-EAV-Attributen einfach
Response-Cache für Produktlisten Sehr hoch (bei Cache-Hit) Mittel Nur anonyme Requests; Cache-Invalidierung nötig
Attribut-Label-Cache im Service Mittel Mittel Nur für Option-Label-Lookups relevant
Elasticsearch/OpenSearch für Suche Sehr hoch (für Suchabfragen) Hoch Nur für Suchabfragen, nicht für direkte Abrufe

8. Caching-Strategien für EAV-lastige Resolver

Der effektivste Cache für EAV-lastige Resolver ist der Magento Response-Cache, der eine vollständige GraphQL-Response für anonyme Queries speichert. Bei einem Cache-Hit wird die Response direkt aus dem Cache gelesen, ohne dass eine einzige Datenbankabfrage stattfindet – EAV-Overhead inklusive. Der Response-Cache erfordert eine korrekt konfigurierte Identity-Klasse, die Cache-Tags setzt, und ist standardmäßig für öffentliche Produktabfragen aktiviert.

Für Resolver, die produktbezogene Attribute zurückgeben und keinen vollständigen Response-Cache nutzen können (etwa authentifizierte Queries), empfiehlt sich ein feldspezifischer Cache auf Service-Ebene. Produktattribute, die sich selten ändern – Name, Beschreibung, URL-Key, Bilder –, können im Magento-Cache oder Redis zwischengespeichert werden. Das Laden dieser Werte aus dem Cache ist um Größenordnungen schneller als ein EAV-JOIN, selbst für einzelne Produkte. Die Cache-Invalidierung erfolgt über die Magento-Indexer, die beim Produktspeichern automatisch ausgelöst werden.

9. Index-Strategie: welche Indizes wirklich helfen

Magento pflegt für die EAV-Tabellen eigene Indizes, aber in großen Installationen mit vielen Custom-Attributen und hohem Traffic können diese nicht ausreichen. Der wichtigste Index für EAV-Performanceabfragen ist ein zusammengesetzter Index auf (entity_id, attribute_id, store_id) in den EAV-Wertetabellen – dieser deckt die häufigsten Abfragmuster ab. In MySQL/MariaDB kann man mit EXPLAIN prüfen, ob bestehende Abfragen diesen Index verwenden.

Für den catalog_product_flat-Index-Prozess selbst ist es wichtig zu verstehen, dass partielle Reindizierungen (nur für geänderte Produkte) möglich sind und in produktiven Systemen deutlich schneller sind als vollständige Reindizierungen. Die Konfiguration von mview.xml und den Index-Mode-Einstellungen bestimmt, wann und wie der Flat-Catalog aktualisiert wird. Realtime-Reindizierung (Update on Save) ist für kleinere Kataloge geeignet; für große Stores mit häufigen Preisänderungen empfiehlt sich geplante Reindizierung außerhalb der Stoßzeiten.


# Query optimized for Flat-Catalog — all requested fields should be in the flat table
# Check with: SHOW COLUMNS FROM catalog_product_flat_1
query FlatCatalogOptimizedQuery {
  products(
    filter: { category_id: { eq: "5" } }
    pageSize: 24
    currentPage: 1
  ) {
    total_count
    items {
      # These fields are typically in the flat table — one SELECT, no EAV JOINs
      sku
      name
      url_key
      status
      visibility
      # Price comes from price index, not EAV
      price_range {
        minimum_price {
          final_price { value currency }
          regular_price { value }
        }
      }
      # Image from media gallery index
      small_image { url label }
    }
  }
}

10. Zusammenfassung

Das EAV-Modell ist der größte versteckte Performance-Faktor bei Magento GraphQL-Produktabfragen. Jedes abgefragte Attribut kann einen oder mehrere JOINs über EAV-Wertetabellen auslösen, und ohne Flat-Catalog multipliziert sich dieser Overhead mit der Anzahl der Produkte in der Ergebnisliste. Profiling mit dem SQL-Query-Logger macht diese Kosten sichtbar und zeigt, wo die meiste Zeit verbracht wird.

Die wirksamsten Gegenmaßnahmen sind Flat-Catalog aktivieren und Custom-Attribute explizit einbinden, Response-Cache für anonyme Produktlisten konfigurieren und feldspezifisches Caching für sich selten ändernde Attribute implementieren. Wer diese Maßnahmen kombiniert, kann die Ladezeit einer typischen Produktlisten-Query um 60–90 % reduzieren – ohne die GraphQL-Schnittstelle oder den Schema-Aufbau ändern zu müssen.

Magento GraphQL & EAV — Das Wichtigste auf einen Blick

EAV-Grundproblem

Jedes Attribut = ein JOIN über eine typisierte Wertetabelle. 20 Produkte × 30 Attribute = potenziell 600 EAV-Zugriffe pro GraphQL-Request ohne Flat-Catalog.

Flat-Catalog

Aktivieren und Custom-Attribute einbinden. Materialisiert EAV-Daten in eine breite Tabelle – ein SELECT statt dutzender JOINs. Größter einzelner Performance-Hebel.

Profiling

SQL-Query-Logger aktivieren und EAV-Queries zählen. EXPLAIN für häufige Queries ausführen und auf fehlende Indizes prüfen. Erst messen, dann optimieren.

Caching

Response-Cache für anonyme Produktlisten ist die effektivste Maßnahme. Feldspezifischer Cache für Attribute, die sich selten ändern, als Ergänzung für authenticated Queries.

11. FAQ: Magento GraphQL und EAV

1Warum ist EAV ein Performance-Problem?
Jedes Attribut = ein JOIN über eine typisierte Wertetabelle. Bei einer Produktliste mit vielen Attributen summieren sich diese JOINs zu hunderten SQL-Operationen ohne Flat-Catalog.
2Was ist der Flat-Catalog und wie hilft er?
Materialisiert EAV-Daten in eine breite Tabelle. Statt vieler JOINs reicht ein SELECT. Aktivieren unter Stores > Configuration > Catalog > Storefront. Größter einzelner Performance-Hebel.
3Muss nach jeder Produktänderung reindiziert werden?
Im Update-on-Save-Modus automatisch für geänderte Produkte. Für große Stores geplante Reindizierung außerhalb der Stoßzeiten empfohlen.
4Welche EAV-Tabellen sind relevant?
entity_varchar, entity_int, entity_decimal, entity_text, entity_datetime – je nach Attributtyp. Alle unter catalog_product_entity_*.
5Wie Custom-Attribut zum Flat-Catalog hinzufügen?
used_in_product_listing = true im Attribut-Setup setzen. Dann catalog_product_flat reindizieren. Konfiguration im Modul über Setup- oder Upgrade-Skript.
6Wie EAV-Performance-Probleme erkennen?
SQL-Query-Logger aktivieren und Queries gegen catalog_product_entity_* zählen. EXPLAIN zeigt ob Indizes fehlen. Mehr als 10 EAV-Queries pro GraphQL-Request ist ein klares Signal.
7Hilft OpenSearch bei EAV-Problemen?
Ja, für Suchabfragen. OpenSearch hält Produktdaten in einem flachen Dokumentenformat vor und umgeht EAV-JOINs für Suchergebnisse. Für direkte ID-Abrufe bleibt EAV relevant.
8Unterschied Response-Cache vs. Attribut-Cache?
Response-Cache: komplette GraphQL-Response gecacht – bei Hit kein PHP, kein SQL. Attribut-Cache: einzelne Attributwerte gecacht – hilft bei auth. Requests ohne Response-Cache.
9Beeinflussen Extension-Attributes dieselben EAV-Tabellen?
Nein. Extension-Attributes werden in eigenen Tabellen gespeichert, nicht in EAV-Tabellen. Eigene JOINs auf klar definierten, indizierten Tabellen ohne EAV-Overhead-Muster.
10Wie viele Custom-Attribute sind noch performant?
Mit Flat-Catalog keine harte Grenze. Ohne Flat-Catalog steigen EAV-JOINs linear. Mehr als 50–100 häufig genutzte Custom-Attribute ohne Flat-Catalog sind ein klares Performance-Risiko.