Modify

Opened 11 years ago

Closed 11 years ago

#426 closed Bug/Fehler (fixed)

Startseite des Shops bei vielen Artikeln (>100.000) sehr langsam

Reported by: Cookie Owned by: somebody
Priority: normal Milestone: modified-shop-2.0.0.0
Component: Shop Version: 2.0.0.0
Keywords: Cc:
Blocked By: Blocking:

Description

Bei sehr vielen Artikeln im Shop wird die Startseite sehr langsam. Die Ladezeit kann bis zu 10 Sekunden betragen. Ich habe mir das Problem schon angeschaut. Es liegt am new_products Modul, welches in der center_modules geladen wird. In der SQL Abfrage für die neuen Produkte ist ein "order by rand()" enthalten. Dies macht die Abfrage sehr langsam. Entfernt man das order by, ist die Geschwindigkeit ok.

Grüße
Christian

Attachments (0)

Change History (6)

comment:1 by Volker Strähle, 11 years ago

Die Abfrage steht in includes/module/new_products.php ca. Zeile 50. Die bestehende Abfrage führ dazu, dass erstmal alle neuen Produkte geladen werden müssen, um dann nur einige wenige auszuwählen.

Lösungsansatz:

        $new_products_query = "        SELECT *
          FROM products AS p JOIN
               (SELECT (RAND() *
                             (SELECT MAX(products_id)
                                FROM products)) AS id)
                                   AS p2
                                   LEFT JOIN ".TABLE_MANUFACTURERS." m
                                             ON p.manufacturers_id = m.manufacturers_id
                                        JOIN ".TABLE_PRODUCTS_DESCRIPTION." pd
                                             ON p.products_id = pd.products_id
                                                AND trim(pd.products_name) != !''
                                                AND pd.language_id = '".$_SESSION!['languages_id']."'
                                        JOIN ".TABLE_PRODUCTS_TO_CATEGORIES." p2c 
                                             ON p.products_id = p2c.products_id
                                        JOIN ".TABLE_CATEGORIES." c
                                             ON c.categories_id = p2c.categories_id
                                                AND c.categories_status = '1'
                                                WHERE p.products_id >= p2.id AND p.products_status = '1'
                                             ".PRODUCTS_CONDITIONS_P."
                                             ".$days."
                                         ORDER BY p.products_id ASC
                                     LIMIT 1";

Das gibt genau ein Produkt zurück. Diese Abfrage kann man nun in einer Schleife mehrmals (MAX_DISPLAY_NEW_PRODUCTS) durchlaufen und das Ergebnis in ein Array packen.

Ein "LIMIT MAX_DISPLAY_NEW_PRODUCTS" führ nicht zu verschiedenen Zufallsprodukten, sondern zu aufeinander folgenden Produkten ausgehende von einm zufälligen Startpunkt.

Nachteil: es reichtnicht nur die Abfrage zu ändern, sonder man muss merh in der o. g. Datei anpasssen.

PS: Bei ca. 15.000 Artikel benötigt die o. g. Abfrage etwa 0,1 sek je Durchlauf auf einem lahmen XAMPP.

Last edited 11 years ago by Gerhard Waldemair (previous) (diff)

comment:2 by Gerhard Waldemair, 11 years ago

Mit diesem SQL habe ich bei einer Datenbank mit ca. 600.000 Artikel ca. 4 Sekunden statt 22 Sekunden und ohne dem Subselect unter 1 Sekunde.

SELECT DISTINCT *
      FROM products p 
 LEFT JOIN manufacturers m
           ON p.manufacturers_id = m.manufacturers_id
      JOIN products_description pd
           ON p.products_id = pd.products_id
              AND trim(pd.products_name) != ''
              AND pd.language_id = '2'
      JOIN products_to_categories p2c 
           ON p.products_id = p2c.products_id
      JOIN categories c
           ON c.categories_id = p2c.categories_id
              AND c.categories_status = '1'
     WHERE p.products_status = '1'
       AND RAND() <= (10 * 2 / (SELECT count(p.products_id) FROM products p))
     LIMIT 10
Last edited 11 years ago by Torsten Riemer (previous) (diff)

comment:3 by Gerhard Waldemair, 11 years ago

Ich habe gerade mal den SQL von webald in meiner DB probiert. Der dauert bis zu 6 Sekunden ... Es Waren aber auch Abfragen um ca. 1 Sekunde mit dabei. Wenn ich das dann für 10 Artikel machen muss, sehe ich keinen Vorteil gegenüber einem ORDER BY RAND().

Was aber auch gesagt werden muss: die Zufallsgenerierung bei meinem SQL ist nicht so gut, aber es ist noch Zufall.

Last edited 11 years ago by Gerhard Waldemair (previous) (diff)

comment:4 by noRiddle, 11 years ago

Wo seht Ihr ein ORDER BY RAND() ?, zumindest gibt's den nicht in der 1.06 rev4642 SP2.

Ich denke, daß noch eher das Modul upcoming_products bei sehr vielen Artikeln die Parse-Time hochschraubt. Dort wird nach Datum verglichen (to_days(products_date_available) >= to_days(now())) und das muß für alle Artikel gemacht werden.
Wenn dann noch im Backend das "Sortierfeld für Artikelankündigungen" welches für das ORDER BY im Query benutzt wird, auf date_expected steht, gute Nacht.

In der Tabelle products sollte imho ohnehin jeder nach seinen Bedürfnissen Indizes setzen. Z.B. ist ein Shop wo viel nach Artikelnummern gesucht wird weit schneller in der Suche wenn auf products_model ein Index sitzt.

Ob man generell auf products_date_available einen Index setzen sollte bleibt also fraglich.
Auch machen mehr Indizes den oft in Shops verwendeten Import von vielen Artikeln langsam.

comment:5 by Volker Strähle, 11 years ago

Ich habe mal weiter getestet (200.000 Artikel, davon ca 180.000 neu).

  1. p.products_date_added  BETWEEN DATE_SUB(NOW(), INTERVAL 10 DAY) AND NOW()
    

hat sich als schnellste Version erwiesen.

  1. Lösung kann vermutlich nur eine neue, indizierte Spalte in products sein, die viele Artikel rausfiltert (kein Bild, kein Bestand, ...).
  1. Ganz wichtig wäre es die Anzeige neuer Artikel dekativieren zu können bzw. automatich bei mehr als 10.000 neuen Artikel zu deaktivieren. Falls nicht besteht die Gefahr, dass der Shop nach Massenimport blockiert.
  1. der Join auf Tabelle Manufacturer war zeitlich irrelevant.

Ebenfalls davon betroffen ist templates/tpl/source/boxes/whats_new.php

Eine weitere Lösung könnte sein beim Anlegen neuer Artikel die neusten Artikel in einer neuen Spalte "new_product" zu markieren und eine maximale Anzahl so markierter Artikel festlegen. Kann automatisch erfolgen.

comment:6 by Gerhard Waldemair, 11 years ago

Resolution: fixed
Status: newclosed

In 8275:

fix #426

Modify Ticket

Action
as closed The owner will remain somebody.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.