ständige SQL-Queries lahmen Shop

Hallo,
seit 1 Tag ist mir aufgefallen, dass unser Shop ziemlich langsam läuft. Unser Hoster meint dazu, dass folgender Querie ständig aufgerufen wird:

SET timestamp=1528195885;
SELECT SQL_CALC_FOUND_ROWS product.id as __product_id, variant.id as__ variant_id, variant.ordernumber as __variant_ordernumber FROM s_articles product
INNER JOIN s_articles_details variant ON variant.id = product.main_detail_id
AND variant.active = 1
AND product.active = 1
LEFT JOIN s_articles_avoid_customergroups avoidCustomerGroup ON avoidCustomerGroup.articleID = product.id AND avoidCustomerGroup.customerGroupId IN (1) INNER JOIN s_articles_categories_ro productCategory ON productCategory.articleID = product.id AND productCategory.categoryID IN (467) INNER JOIN (SELECT prices.*, MIN(ROUND(prices.price * availableVariant.minpurchase * ((100 - IFNULL(priceGroup.discount, 0)) / 100) * (( (CASE tax.id WHEN 1 THEN 19 WHEN 4 THEN 7 END) + 100) / 100) * 1, 2)) as cheapest_price FROM s_articles product INNER JOIN s_core_tax tax ON tax.id = product.taxID INNER JOIN (SELECT `id`, `pricegroup`, `from`, `to`, `articleID`, `articledetailsID`, `price`, `pseudoprice`, `baseprice`, `percent` FROM s_articles_prices defaultPrice WHERE defaultPrice.pricegroup = 'EK') prices ON product.id = prices.articleID INNER JOIN s_articles_details availableVariant ON availableVariant.articleID = product.id
             AND availableVariant.active = 1 LEFT JOIN s_core_pricegroups_discounts priceGroup ON priceGroup.groupID = product.pricegroupID
             AND priceGroup.discountstart = 1
             AND priceGroup.customergroupID = '1'
             AND product.pricegroupActive = 1 WHERE (prices.articledetailsID = availableVariant.id) AND (prices.from = 1) GROUP BY product.id) listing_price ON listing_price.articleID = product.id INNER JOIN s_articles_attributes productAttribute ON productAttribute.articledetailsID = variant.id WHERE avoidCustomerGroup.articleID IS NULL GROUP BY product.id ORDER BY listing_price.cheapest_price ASC, product.id ASC;

Könnt Ihr mir helfen und mir mitteilen, wo ich ansetzen kann?

Danke

Ich vermute viel mehr, dass hier MySQL nicht richtig für SW optimiert ist oder der Hoster ist generell für SW nicht geeignet.

Hallo,

 

das sieht nach einem Doctrine Query aus. Könnte an einem Plugin liegen. Also einfach mal Plugins deaktivieren und schauen, ob der Fehler weiterhin besteht. Da es hier um Kundengruppen geht, vermute ich mal du hast Business Essentials im Einsatz?

 

 

MFG

 

derwunner

Danke für eure Rückmeldungen, Shopware hat sich auch zu dem Thema geäußert, es wären normale abfrage, serverseitig kamen wir aber nicht hinterher.

Wir haben uns aus diesem Grund entschieden, den Hoster zu wechseln und seit dem läuft alles wieder wie gewünscht.

Ich muss das Thema noch einmal hoch holen. Bei unserem neuen Provider mit noch mehr Leistung wie vorher, haben wir bei gleicher Installation (PE 5.4.4 mit PHP 7.0.27) wieder diese ständigen Querys:

# Time: 181023 19:30:02
# User@Host: xxxxxxxx @ localhost []
# Thread_id: 11943940 Schema: xxxxx QC_hit: No
# Query_time: 6.659450 Lock_time: 0.000099 Rows_sent: 1 Rows_examined: 7586978
# Rows_affected: 0
use xxxxxx;
SET timestamp=1540315802;
SELECT listing_price.cheapest_price FROM s_articles product INNER JOIN s_articles_details variant ON variant.id = product.main_detail_id
                 AND variant.active = 1
                 AND product.active = 1 INNER JOIN s_articles_categories_ro productCategory5 ON productCategory5.articleID = product.id
            AND productCategory5.categoryID IN (833) LEFT JOIN s_articles_avoid_customergroups avoidCustomerGroup ON avoidCustomerGroup.articleID = product.id
             AND avoidCustomerGroup.customerGroupId IN (1) INNER JOIN (SELECT prices.*, MIN(ROUND(prices.price * ((100 - IFNULL(priceGroup.discount, 0)) / 100) * (( (CASE tax.id WHEN 1 THEN 19 WHEN 4 THEN 7 END) + 100) / 100) * 1, 2)) as cheapest_price FROM s_articles product INNER JOIN s_core_tax tax ON tax.id = product.taxID INNER JOIN (SELECT defaultPrice.`id`,defaultPrice.`pricegroup`,defaultPrice.`from`,defaultPrice.`to`,defaultPrice.`articleID`,defaultPrice.`articledetailsID`,defaultPrice.`price`,defaultPrice.`pseudoprice`,defaultPrice.`baseprice`,defaultPrice.`percent` FROM s_articles_prices defaultPrice WHERE defaultPrice.pricegroup = 'EK') prices ON product.id = prices.articleID INNER JOIN s_articles_details availableVariant ON availableVariant.articleID = product.id
             AND availableVariant.active = 1 LEFT JOIN s_core_pricegroups_discounts priceGroup ON priceGroup.groupID = product.pricegroupID
             AND priceGroup.discountstart = 1
             AND priceGroup.customergroupID = '1'
             AND product.pricegroupActive = 1 WHERE (prices.articledetailsID = availableVariant.id) AND (prices.from = 1) GROUP BY product.id) listing_price ON listing_price.articleID = product.id INNER JOIN s_articles_attributes productAttribute ON productAttribute.articledetailsID = variant.id WHERE avoidCustomerGroup.articleID IS NULL GROUP BY product.id ORDER BY listing_price.cheapest_price ASC LIMIT 1 OFFSET 0;

Diese ständigen Abfragen lahmen unseren Shop immens aus. Liegt die Seite im Cache, wird sie auch schnell (wie gewohnt) aufgerufen.
Das Phänomen tritt auch nur auf den listing-Seiten auf, CMS sowie Artikel-details laufen wie gewohnt schnell. Aber eine ungecachte Seite kann bis zu 20 Sekunden dauern Frown

Zusätzlich habe ich im Unterordner der Liveumgebung eine 1zu1 Kopie als Testversion, wo dieses Problem nicht auftritt.

Heute habe ich in der Liveumgebung den Plugin-Sicherheitsmodus aktiviert (alle community sowie local-Plugins wurden dadurch deaktiviert), dann noch zusätzlich das Standard Responsive-Theme aktiviert -> gleiches Problem. Eine ungecachte Seite braucht teilweise bis 20 Sekunden, eine gecachte unter einer Sekunde.

Cache aufwärmen ist für mich nur eine Option, keine Lösung. Das Problem tritt auch merkwürdigerweise erst wieder seit einer Woche auf, Änderungen wurden nur an den Plugins unternommen, welche auch wieder rückgängig gemacht wurden bzw. eben deaktiviert wurden.

Unser Provider (Timme) meint auch, man kann am Server weitere Optimierungen vornehmen (Redis, ElasticSearch etc.) aber mich wunder eben, warum es erst seit einer Woche wieder ist. Vorher lief bei gleicher Anzahl an Artikel auch alles wie gewohnt und die Testumgebung, welche im Unterordner liegt, rennt auch wie sie soll (beim ersten Aufruf einer Kategorieseite).

Hat ggf. jemand einen Tipp für mich?

Amazon Pay aktiv?

Nein, das nutzen wir seit mehreren Wochen nicht mehr, das war auch immer mit mein erster Gedanke mit.

Laut SQL wird immer nach dem günstigsten Preis sortiert. Das ist im Standard nicht der Fall. Ist die Sortierung dort angepasst?

Kannst du mal auf die Standardeinstellungen gehen und prüfen, ob dann diese Statements noch so auftauchen? Dann hätte man das Thema eingegrenzt und kann da genauer nachschauen 

Zusätzlich können dir Artikel selbst auch ausschlaggebend sein. Preisgruppen aktiv, besondere Preisdefinitionen oder sehr viele Konfigurator Artikel usw usw

Herr Klöpper, vielen Dank für Ihren Hinweis, das war der entscheidene. Wir sortieren nach dem niedrigsten Preis. Das alleine reichte aber nicht aus umzustellen, ich musste bei unserer Artikelanzahl auch alle Filter ausstellen bzw. den Preisfilter (wir nutzen sehr viele Varianten).

Jetzt wäre es wirklich überlegenswert ElasticSearch/Redis einzusetzen, um die Filter wieder nutzen zu können bzw. weiterhin nach dem niedristen Preis zu sortieren.

Eine Frage hätte ich noch:
Gibt es Performanceunterschiede zwischen der Sortierung nach Erscheinungsdatum und nach Beliebtheit?

Ebenso frage ich mich, warum diese Einbußen mit einmal kamen und in der Testumgebung nicht auftreten?! Aktuell kann ich aber mit der Lösung absolut leben und optimiere nun weiter an den Einstellungen.

Das sieht sehr Stark nach den Varianten Filter aus. Wie viele Produkte hast du denn im Shop? Wenn es sehr viele sind, solltest du dir überlegen Elasticsearch einzusetzen.

Filter ansich habe/hatte ich aber nur den Hersteller- sowie Preisfilter aktiv. Mit deaktiviertem Preisfilter sowie Standardsortierung nach Erscheinungsdatum läuft es wieder wie gewünscht sehr schnell.

Wir setzen aktuell ca. 20.000 Hauptartikel ein, viele davon besitzen aber Varianten bis teilweise 500 Kinder unter sich. Macht insgesamt aktuell ca. 90.000 Artikel.

Welche Shopware Version setzt du ein? Probiere mal bitte in den Grundeinstellungen unter Storefornt -> Warenkorb / Artikeldetails -> Abverkaufsartikel ohne Lagerbestand ausblenden -> Ja, zu konfigurieren. Im Tooltip wird auch erläutert, dass die negierte Option die Performance im Listing beeinflussen kann.

Wir setzen 5.4.4 ein.
Danke für Ihren Tipp, wir nutzen aber keine Bestandsführung für unsere Artikel.

Wissen Sie ggf. ob es Performanceunterschiede zwischen der Sortierung nach Erscheinungsdatum und nach Beliebtheit gibt?
Wir wollen die Tage mal noch die Sessions ins Redis auslagern und dann mit der Sortierung nach dem niedrigsten Preis noch einmal probieren.

Da ist mir nichts bekannt. Was mir noch einfällt: habt ihr eine WaWi oder ähnliches  welche die Artikel aktualisiert? Du könntest mal in der s_articles_prices schauen ob du hier vielleicht noch viele alte Preisdatensaetze drin hast. Am besten mal vergleichen ob das mit der Anzahl der Artikel stimmt.

 

LG Andre

Hallo Andre,

danke für den Tipp, die Anzahl der Datensätze passt 1zu1 zu den Artikeln, die wir eingespielt haben. Können wir somit auch abhaken.

Grundsätzlich läuft mein Shop wieder wie hanne und ich bedanke mich für die Unterstützung.

VG Thomas

@AndreHerking‍ Sorry, wenn ich das Thema hier nach so langer Zeit noch mal ausgrabe. Wir haben ein recht ähnliches Problem mit den Abfragen. Zwischenzeitlich hat sogar die Suche nicht mehr gewollt.

Das Abschalten der Preisfilter hat sehr viel gebracht. (Suche geht wieder, Performance allgemein besser.) Allerdings können wir nicht mal eben die ausverkauften Artikel ausblenden. Das führt dann zu kuriosen Effekten, wie etwa, dass Artikel, die in Einkaufswelten verlinkt sind, plötzlich nur noch mit dem Platzhalterbild zu sehen sind.

Unsere Sorgen-Kategorie ist “Angebote”. Die basiert auf einem Product-Stream, der Artikel sammelt, die einen Pseudopreis gepflegt haben und sofort verfügbar sind (und unterhalb einer der Hauptkategorien zu finden sind). Lassen wir die ausverkauften Artikel ausblenden, ist die Anzeige pfeilschnell. Setze ich die Option auf “Nein”, lädt die Kategorie beim ersten Aufruf etwa eine Minute – DB-Last ist entsprechend hoch. (Dann ist es im Cache und alles wieder schnell. Aber Product-Streams werden wohl ziemlich schnell invalidiert.)

Meine Frage ist jetzt, ob wir noch eine andere Stellschraube haben? Könnte man beispielsweise das Ausblenden der ausverkauften Artikel nur bei “Angebote” anschalten? Bringt ein Update auf Version 5.5 etwas? (Aktuell Version 5.4.6)

ElasticSearch können wir nicht einsetzen, da das anscheinend immer noch nicht mit der Intelligenten Suche zusammen funktioniert. Gibt es eine Aussicht, dass sich das irgendwann ändern wird? Oder kommt vielleicht eine Lösung, bei der man ElasticSearch für bestimmte Bereiche nutzen kann und für andere nicht?

Hallo zusammen,

auch wir haben diverse Kunden, welche von dem Problem betroffen sind. Schuld ist hier scheinbar die sehr inperformante Preisermittlung, welche zur Abfragezeit mit jeder Query stattfindet, sofern nach Preis sortiert oder gefiltert wird.
Extrem schlimm bis unbenutzbar wird es, wenn man noch einen Varianten-Filter setzt.

Eine temporäre Lösung ist hier, alle Preisfilter und Preissortierungen zu deaktivieren. Da aber insbesondere die Sortierung “Preis aufsteigend” sehr häufig genutzt wird, ist dies eigentlich keine dauerhafte Option.

Auch ein Wechsel auf Elasticsearch stellt in vielen Projekten keine Option dar, da die Artikelmenge im Shop eigentlich zu gering ist oder der Kunde die absolut sinnvollen Features der “intelligenten Suche” fordert. (Diese ist nicht mit Elasticsearch kompatibel.)

Mein Lösungsvorschlag wäre hier, analog z.B. zum “Topseller-Index” einen “Preis-Index” zu erstellen, welcher für jeden Artikel und jede Variante pro Kundengruppe/Rabattgruppe etc. die niedrigsten, höchsten sowie die Pseudopreise vorhält. Die aufwändige Preisermittlung würde dann z.B. via Cronjob nur einmalig erfolgen und nicht bei jedem Kategorieseiten-Aufruf staffinden.

Ich habe dazu ein Ticket erstellt: https://issues.shopware.com/issues/SW-23922. Vielleicht gibt es hier ja seitens Shopware noch eine Lösung für die SW5-User.

Wir haben uns inzwischen mit einem mehrstufigen Workaround geholfen:

  • Doofinder statt Intelligenter Suche

  • Cache-Vorhaltezeiten von einem Tag auch auf die Listing-Controller-Actions

  • Preis-Sortierungen usw. zumindest teilweise deaktiviert

  • Wechsel auf PHP 7.2

Der erste Punkt war eigentlich in Vorbereitung auf die Nutzung von ElasticSearch gedacht. Aber aus einem mir nicht erklärbaren Grund, hat das keine Veränderung bei den Ladezeiten gebracht. (Und im Backend ist ElasticSearch in der jetzigen Form ohnehin nicht einsetzbar. Da klappt ja gar kein Artikel-Filter mehr!)

Der zweite Punkt hat die schlimmste Kategorie bei uns endlich wieder benutzbar gemacht. Durch die Vorhaltezeit von einem Tag, lädt sie jetzt quasi immer schnell. Bonus: Allgemein haben wir die Ladezeiten in Listings deutlich drücken können. Allerdings ist das eigentlch keine Lösung für Shops, die viele Änderungen an Artikeln oder Preisen vornehmen. Im Zweifel steht in der Liste noch ein alter Wert.

Den dritten Punkt müssen wir noch mal genauer überprüfen. Sicher lässt sich das für viele Kategorien wieder aktivieren. Durch Doofinder gibt es direkt in der Suche eine Preisfiltermöglichkeit.

Der Wechsel auf PHP 7.2 (und Shopware Version 5.5.7) hat allgemein die Performance verbessert. Gerade im Backend spüren wir das deutlich.

Um das Thema Ladezeiten und Cache mal ein wenig weiter zu denken: Ich frage mich, ob die derzeitige Caching-Strategie noch up-to-date ist. Meiner Meinung nach müsste man das von der anderen Seite aus aufzäumen – ähnlich dem Caching, das Google bei den AMP-Seiten vornimmt. Dort wird initial eine Version im Cache abgelegt und nach einem Besuch (und wahrscheinlich einem zeitlichen Threshold) wird geprüft, ob es eine neuere Version gibt und der Cache ggf. aktualisiert. Letztlich wird also immer aus dem Cache geliefert und wenn es nichts neues gibt, beibt der Cache erhalten.

Eigentlich wären das nur leichte Anpassungen, die man in Shopware vornehmen müsste:

  • Statt beim Seitenaufruf zu prüfen, ob die Cache-Vorhaltezeit abgelaufen ist, verschiebt man die Prüfung danach. Dann Prüfung nach Zeit X (wie bisher) und ggf. (asynchron) aktualisieren.

  • Cache-Invalidierungen können wie bisher beibehalten werden. Die entsprechenden Seiten würden aber auch gleich wieder in den Cache geschrieben.

  • Cache-Warm-up usw. könnten beibehalten werden. Wobei auch hier der Bonus darin bestehen würde, dass das Triggern des Cache-Warm-ups selbst gegen den Cache läuft und erst nachgelagert bzw. asynchron die Aktualisierung des Caches erfolgt.

Bei den Invalidierungen wären vielleicht noch ein paar Erweiterungen interessant. So müsste meiner Meinung nach beim Speichern eines Artikels nicht nur die Detailseite invalidiert werden, sondern auch alle Kategorien und ProductStreams (bzw. die Kategorien, die den jeweiligen ProductStream nutzen), in denen der Artikel drin ist.

Die Ziele sollten klar sein: Möglichst immer schnell die Seiten ausliefern und dabei trotzdem die Aktualität garantieren.

Hallo zusammen,

ich habe für unsere Zwecke nun ein Plugin programmiert, welches mit etwas Hilfe der “Shopware-Bordmittel” einen “Preisindex” erstellt.

Das Plugin legt ein verstecktes Artikel-Freitextfeld und einen Shopware-Cronjob an. Der Cronjob befüllt dann einfach das Feld mit dem niedrigsten Preis des Artikels für die Kundengruppe “EK”. Steuersätze werden hier aktuell nicht berücksichtigt, da eh immer nur Artikel mit 19% vorhanden sind. Ebenfalls werden andere Kundengruppen nicht betrachtet.

In den Shopware-Grundeinstellungen deaktiviert man dann die Standard-Preissortierungen und legt neue Sortierungen mit Artikel-Freitextfeld “Preisindex” auf/absteigend an. Funktioniert auch bei vielen Artikeln und gesetzen Varianten-Filtern rasend schnell!

Selbstverständlich werden jetzt nicht alle in Shopware möglichen Situationen der Preisermittlung abgedeckt. Für den “Standard-Fall” erfüllt es jedoch genau den Zweck! :slight_smile:

Bei Interesse gerne melden. :slight_smile:

1 „Gefällt mir“