私は私たちのサイトの販売ランキング ウィジェットに取り組んでいます。これは、「トップ チャート」または「ベストセラー」リスト (いわば) での現在の位置で並べ替えられた製品を表示します。
少し読んだ後、これを実装するための良い方法は、最近の販売ほど重み付けが高くなる単純なローリング販売平均アルゴリズムであるように見えます。
例:
$rolling_avg = ((4*$d1)+(3*$d2)+(2*$d3)+$d4+$d5+$d6+$d7)/13;
どこ:
- $d1 = 過去 24 時間の売上数。
- $d2 = 過去 24 ~ 48 時間の売上数。
- $d3 = 過去 48 ~ 72 時間の売上数。
- $d4 = 過去 72 ~ 96 時間の売上数。
等々...
現在、約 500k レコードの製品データセットでこれを実行しようとしており、計算されたランクを製品テーブルに挿入して、後で照会できるようにしています。可能であれば、ランキングを再計算するスクリプトを作成し、これを 12 時間または 24 時間ごとに cron で実行できるようにしたいと考えています。
現在の実装:
私の現在の実装は実行に時間がかかりすぎており、SQL レベルでより多くの処理を実行する必要があると感じています (SELECT クエリははるかに少ない) が、これを開始する方法がわかりません。
$products = mysql_query("SELECT * FROM products ORDER BY id DESC"); // <-- Est 450-500k rows.
while($product = mysql_fetch_array($products)) {
$product_id = $product['id'];
$d1 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 24 HOUR) AND NOW())") or die(mysql_error);
$d1 = mysql_fetch_array($d1);
$d2 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 48 HOUR) AND (NOW()-INTERVAL 24 HOUR))");
$d2 = mysql_fetch_array($d2);
$d3 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 72 HOUR) AND (NOW()-INTERVAL 48 HOUR))");
$d3 = mysql_fetch_array($d3);
$d4 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 96 HOUR) AND (NOW()-INTERVAL 72 HOUR))");
$d4 = mysql_fetch_array($d4);
$d5 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 120 HOUR) AND (NOW()-INTERVAL 96 HOUR))");
$d5 = mysql_fetch_array($d5);
$d6 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 144 HOUR) AND (NOW()-INTERVAL 120 HOUR))");
$d6 = mysql_fetch_array($d6);
$d7 = mysql_query("SELECT COUNT(*) FROM orders WHERE (product_id = '$product_id') AND (sale_completed BETWEEN (NOW()-INTERVAL 168 HOUR) AND (NOW()-INTERVAL 144 HOUR))");
$d7 = mysql_fetch_array($d7);
$d1 = $d1[0];
$d2 = $d2[0];
$d3 = $d3[0];
$d4 = $d4[0];
$d5 = $d5[0];
$d6 = $d6[0];
$d7 = $d7[0];
$rolling_avg = ((4*$d1)+(3*$d2)+(2*$d3)+$d4+$d5+$d6+$d7)/13;
mysql_query("UPDATE products SET rolling_sales = '$rolling_avg' WHERE id = '$product_id'");
}
ここから最適化/進行する方法がわかりません。しかし、それには間違いなく多くの作業が必要です。
言及する前に、関数が減価償却されていることを理解mysql_*
しています。これを本番環境に移行する前に PDO に移行します。