1

現時点では、ユーザーが最近見たものの簡単な履歴ページを表示できるように、ユーザーの過去20回のメディアビューを記録しています。

これを行うには、メディアIDをテーブルに挿入します。

テーブルを小さいサイズに保つために、現在はユーザーあたり20アイテムしかないため、行を挿入する前に、現在そこにある履歴IDの数を確認します。20未満の場合は、新しい行を挿入します。 20次に、新しい行を挿入する前に、最後の行を選択して削除する必要があります。

$historyResult = mysql_query("SELECT id FROM mediatable WHERE userId = $userId ORDER BY id ASC");

if(mysql_num_rows($historyResult) >= 20)
{
    $historyResult = mysql_query("SELECT id FROM mediatable WHERE userId = $userId ORDER BY id ASC LIMIT 1");
    $historyRow = mysql_fetch_row($historyResult);
    mysql_query("DELETE FROM mediatable WHERE id = '$historyRow[0]'");
}

mysql_query("INSERT INTO mediatable (userId, mediaId) VALUES ($userId, $mediaId))");

私は現在、サイトをより最新のコードに変換しており、pdoクエリを使用する予定です。私の質問は次のとおりです。

上記はこれにアプローチするための良い方法ですか、それとも挿入時にMySQLトリガーなどの別の方法を使用する必要がありますか?

4

3 に答える 3

7

最大速度に本当に関心がある場合は、最初に行数をチェックせず、クリーンアップ操作でバックグラウンドで行を削除するという非常にパフォーマンスの高いオプションもあります。新しい行を挿入するときはいつでも、直接挿入してください。表示する最新の行をフェッチするときは常に、を使用してLIMIT 20ください。

ガベージコレクタープロセスは、これとは独立して必要な頻度で実行でき、20を超える履歴レコードを持つユーザーを探し、最も古いものを適切に削除します。このようにして、最近の履歴アイテムの下限が保証され(ある時点で作成されている場合)、プルーニングを待機している古い履歴レコードの量は無制限ですが、実際にはかなり少なくなります。収集頻度はお好みで決めることができます。

一方、絶対的なパフォーマンスではない場合は、PHPからのチェックで問題ありません。ただし、SELECT COUNT(*) FROM mediatable WHERE userId = $userId既に存在するIDの数を調べるときに実行するように変更する必要があります。このようにして、将来の保持戦略を変更することもはるかに簡単になります。

更新:考慮すべきガベージコレクション戦略

  1. スケジュールされたGC:収集は定期的に行われ、ほとんどの場合、固定されたスケジュールで行われます。通常、これはOSに応じて、cronジョブまたはスケジュールされたタスクとして実装されます。利点には、信頼性と、履歴データを使用して、剪定されるのを待っているアイテムの標準偏差を大幅に減らすオプションが含まれます。さらに、クリーンアップは1人のユーザー要求に関連付けられていません(ブロックされるべきではありません)。これにより、コンテンツが利用可能になる前にユーザーがGCの完了を待たなければならない(通常はまれな)機会がなくなります。
  2. 確率的GC:収集はランダムにトリガーされます。アプリケーションは、GCをトリガーできる一連のアクション(たとえば、新しい履歴アイテムの作成)と、そのセット内のアクションが発生するたびにGCがトリガーされる確率を指定します。収集は、アクションの処理の一部として実行することも、コレクターをオンデマンドで起動する別個のプロセスにすることもできます。最も重要な利点は、アプリケーションの外部でセットアップが必要ないことです。これは、アプリが広く配布されることを意図していない場合はそれほど重要ではない可能性があります。単位時間あたりのトリガーアクションの平均数を考慮しながらGC確率を調整すると、連続するコレクション間の目的の間隔を(大まかにではありますが)ターゲットにすることができます。
于 2012-05-29T20:20:34.353 に答える
1

以下は、ユーザーがすでに20を超える行を挿入している場合に、新しい行を挿入するか、既存のIDを再利用します。クエリは、このユーザーの最も古い既存のIDを使用します。

mysql_query("
INSERT INTO mediatable (id, userId, mediaId) 
    SELECT m.idd, d.u, d.m
    FROM 
        (SELECT " . $userId . " u, " . $mediaId . " m FROM dual) d LEFT JOIN (
                    SELECT userid u, MIN(id) idd FROM mediatable
                    WHERE 
                        userid = " . $userId . "
                    GROUP BY 
                        userid
                    HAVING COUNT(*) > 20
                ) m ON d.u = m.u
");
于 2012-05-29T20:34:41.613 に答える
0

最善の方法は、1つのストアドプロシージャを作成し、新しいデータを渡すだけです。最大長
は最大長です。これは、20が大きくなるため、変更が必要になる可能性があるため、動的な方が優れています。
トリガーも優れていますが、プリコンパイル済みです。手順は、速度とカスタマイズの観点から比較するとより良いでしょう。

于 2012-05-29T20:20:19.800 に答える