Nudge am 31.07.2008

SQL im Webshop: Suche nach Modified

in MySQL, PHP, Web | Tags: Cache, MySQL, Performance, Query, SQL, Webshop

Größere Netzwerke, Suchmaschinen oder auch mal eben der kleine Statusbalken arbeiten viel besser, wenn man einen Zeitstempel zur Verfügung stellen kann à la “Dieser Artikel oder dieses Produkt wurde zuletzt geändert am …”.

Das ist allerdings nicht ganz so easy, wenn sich die Daten des Satzes in verschiedenen Tabellen befinden. Also muss man die sich mühevoll zusammenklauben. Bei uns im Shop sind es eigentlich nur eine Handvoll Tabellen: Der Artikeleintrag in der Warenwirtschaft, die Varianten, die Preise, Rabatte, Shop-Eintrag, Shop-Texte und Shop-Fotos.

Die Einträge wurden aus eben diese Tabellen zusammengesucht. Aus Performance-Gründen bieten sich hier Stored Procedures an:
DELIMITER ‘$’;
CREATE FUNCTION f_getModified(…xyz…) RETURNS Datetime READS SQL DATA
BEGIN
DECLARE last DATETIME;
DECLARE cur DATETIME;
SELECT Timestamp INTO last FROM Tbl_XYZ INTO last WHERE xyz;
SELECT Timestamp INTO cur FROM Tbl_XYZ cur WHERE xyz;
SET last = IF(cur > last, cur, last);

RETURN last;
END$
DELIMITER ‘;’$

Natürlich schrumpft die Performance bei zunehmender Fragmentierung der Produktdaten erheblich, da die Berechnungskosten linear steigen. Aus diesem Grund habe ich überlegt, die Tabellen über INNER JOINS zu verknüpfen, und die Zeitstempel zunächst in einem Ritt zu holen:
DELIMITER ‘$’;
CREATE FUNCTION f_getModified(…xyz…) RETURNS Datetime READS SQL DATA
BEGIN
DECLARE last DATETIME;
DECLARE cur DATETIME;
SELECT a.Timestamp, b.Timestamp INTO last,cur FROM Tbl_XYZ a INNER JOIN TblXYZ b ON a.x=b.x AND a.y=b.y WHERE xyz;
SET last = IF(cur > last, cur, last);
RETURN last;
END$
DELIMITER ‘;’$

Auf meine 7 Tabellen angewendet, gibt das immerhin einen 10%-igen Performance-Schub. Nicht unerheblich, aber trotzdem nicht der Bringer. Anfangs waren es über 50% Geschwindigkeitsvorteil, als ich mit einfachen INNER JOINS über die ersten Tabellen arbeitete. Doch da es nicht immer entsprechende Einträge geben muss, ist man hier und da gezwungen, ein paar LEFT JOIN einzusetzen, welche als OUTER JOIN natürlich langsamer sind.

Ein weiteres Problem ist, dass nicht alle Tabellen einen Eintrag pro Produkt bieten, d.h. an dieser Stelle sind Sub-SELECTS vonnötigen, die den Zeitstempel über MAX(Timestamp) zunächst in der Ziel-Tabelle aggregieren, bevor der INNER JOIN einsetzt.

Letztendlich hatte ich bei einer entsprechend aufbereiteten Seite doch eher dazu tendiert, die bereits mit dem PHP-Script ausgelesenen Timestamps und die fehlenden Stempel per Hash-Scan zu ergänzen. An dieser Stelle konnte ich die Kosten für die Zeitstempel auf 20% der Procedure-Kosten drücken – allerdings ist diese Vorgehensweise nicht an allen Stellen die beste.

Doch bietet eine Seite nicht auch noch mehr? FAQs? Bewertungen? Mitkaufartikel? Hat sich die Seite nicht auch deswegen geändert, weil hier und da ein Eintrag dazugekommen ist? Was passiert, wenn sich eine Seite geändert hat, weil ein Eintrag wegfiel? Gar nicht so einfach, und ich möchte gern wissen, wie das “große” Shops so machen…Wer Ideen hat, ist zum Posten gerne eingeladen!


Das mark ich mir: Alltagz Mr Wong Yigg Del.icio.us Yahoo MyWeb Blinklist Google folkd
 

Leave a Reply

Your email address will not be published. Required fields are marked *