Tjena!
Vi har en funktion (som så många andra webbshoppar) där vi visar besökare som besöker en produkt, vilka andra produkter kunder tidigare köpt i samband med den besökta produkten.
SQL-frågan ser ut så här:
'SELECT itemid FROM tbl_orders_items INNER JOIN tbl_products ON itemid = tbl_products.id '.
'WHERE orderid IN (SELECT orderid FROM tbl_orders_items WHERE itemid = '.$a_products['id'].') AND NOT itemid = '.$a_products['id'].' AND tbl_products.status = 1 '.
'GROUP BY itemid ORDER BY count(itemid) DESC LIMIT 3';
Vi har nu c:a 100 000 rader i tbl_orders_items och frågan tar c:a 500-600 ms att utföra på en snabb server, vilket är på tok för lång tid.
Någon som har tips på hur man kan optimera den (eller bygga om den) för att visa samma resultat men snabbare?
Tacksam för hjälp!
/Joel
Om du funderar lite på hur frågan är upplagd (och måste vara upplagd med nuvarande DB-struktur) så inser du att allt måste matchas mot allt, så att säga, innan svaret på frågan kan beräknas.
Den första saken du skulle kunna göra är att bara räkna ut rekommenderade produkter för en viss vara en gång per (tidsperiod) och cacha detta värde. Och när (tidsperiod) har passerat, beräkna värdet igen. Detta är dock bara en temporär lösning som inte löser det grundläggande problemet.
Ett bättre sätt är nog att skapa en relationstabell mellan tbl_products och sig själv där du har en räknare som du räknar upp varje gång för varje försäljning av två varor ihop. Då måste du uppdatera detta för varje order som går igenom. Sedan blir frågan för att hämta ut rekommenderade produkter betydligt snabbare.
Alltså har du fälten productid1, productid2, och buy_count
Du bör definiera att productid1 > productid2. Detta kontrollerar du vid inmatning. Om en rad inte existerar, skapa den, annars inkrementera räknaren.
Minneskomplexiteten är O(n^2). Dvs, om du har 100 produkter, och alla produkter säljs tillsammans med alla produkter kommer du få 100*100=10000 rader i den tabellen.