1

クエリで返されたテーブルのどの ID をログに記録する必要がある API があり、別のクエリでは、ID のログに基づいて並べ替えられた結果を返します。

例えば:

テーブルproductsには と呼ばれる PK があり、 と呼ばれる PK がidありusersましたid。返された ID ごとに 1 つの挿入/更新でログ テーブルを作成できます。性能とデザインが気になります。

基本的に、API で返された ID ごとに、次のようにします。

INSERT INTO log (product_id, user_id, counter) 
    VALUES (@the_product_id, @the_user_id, 1) 
    ON DUPLICATE KEY UPDATE counter=counter+1;

.. PK として id 列を使用するか、product_id と user_id の組み合わせを使用します (代替として、これら 2 つを UNIQUE インデックスとして使用します)。

したがって、最初の問題はこれのパフォーマンスです (20 回の挿入/更新と API での選択呼び出しへの影響)-これらの ID をログに記録するためのより良い/よりスマートな方法はありますか? ウェブサーバーのログから抽出していますか?

2 つ目は、ログに記録されたデータを含めるための select ステートメントのパフォーマンスです。これにより、ユーザーは要求ごとに新製品を表示できます (簡単な例として、実際には * の代わりにテーブル フィールドを指定します)。

SELECT p.*, IFNULL(
    SELECT log.counter 
    FROM log 
    WHERE log.product_id = p.id 
    AND log.user_id = @the_user_id
, 0 ) AS seen_by_user 
FROM products AS p
ORDER BY seen_by_user ASC

私たちのデータベースでは、products テーブルに何百万もの行があり、users テーブルは急速に拡大しています。このようにするのは正しいと思いますか、それとももっと良い方法がありますか? プロセスを最適化するにはどうすればよいですか? また、使用できるツールはありますか?

4

2 に答える 2

3

Callie、キーモンに別の視点をフラグしたかっただけで、コメントに収まらないため、この回答です。

パフォーマンスはインフラストラクチャ環境に左右されます。共有ホスティング サービス (SHS)、専用のプライベート仮想サービス (PVS) または専用サーバーで実行しているか、あるいは個別の Web サーバーとデータベース サーバーを使用するマルチサーバー構成で実行しているか。

取引レートとボリュームはどのくらいですか? 1 日の 2 つのピーク取引時間で、1 分あたり何回の挿入/更新を行っていますか? ログカウンターの古さに対する整合性の要件は何ですか?

はい、たとえば 1 秒あたり 3 ~ 10 回の更新を行っている場合、keymone のポイントは適切です。このドメインに移行すると、一括挿入を可能にするために挿入をバッチ処理するための何らかの形式の収集プロセスが不可欠になります。しかし、ここで重要なのは、ストレージ エンジンの選択、トランザクション分割とバッチ分割、およびインフラストラクチャ アーキテクチャ自体の選択 (サーバー内 DB インスタンスと個別 DB サーバー、マスター/スレーブ構成など) です。

ただし、平均が 1/秒未満の場合、INSERT ON DUPLICATE KEY UPDATE は同等の UPDATE ステートメントと同等のパフォーマンスを持ち、単一行の挿入/更新を行う場合は、カウントの ACID 整合性が保証されるため、より優れたアプローチです。

どのような形式の PHP プロセスの起動も、通常、Web サーバー上で 100 ミリ秒程度かかるため、非同期更新を行うことを考えても、更新自体よりも大幅にパフォーマンス ヒットが大きくなるため、まったくおかしなことになります。

SQL ステートメントは、すべての行で相関サブクエリを実行する製品テーブルの完全なフェッチを行うため、製品テーブルに「何百万もの行」があるというコメントとは一致しません。私なら、LEFT OUTER JOIN を自分で使用し、この結果セットに適した製品アイテムをフィルタリングするための何らかの強い制約を使用します。どのように実行しても、そのすべてのカウント更新を実行するには、大幅に時間がかかります。

于 2012-06-29T15:45:20.950 に答える
2

このようなアプローチでは、パフォーマンスが非常に悪くなります。

mysql はロギングにはあまり適していないため、良好なパフォーマンスを達成するために実行できるいくつかの手順を次に示します。

  1. 統計テーブルをその場で維持するのではなく (パフォーマンスを完全に破壊する重複キー ビットの更新)、単一の生ログ テーブルを用意して、挿入を行い、時々 (たとえば毎日) 実行する必要があります。そのテーブルのデータを実際の統計テーブルに集約するスクリプト。

  2. 単一の統計テーブルを持つ代わりに、毎日の統計、毎月の統計などを持ちます。集計ジョブは、すでに集計されたものからデータを構築します-パフォーマンスに優れています. また、時間の経過とともに統計の粒度をドロップ (またはアーカイブ) することもできます。または、少なくともそれらの統計への「リアルタイム」アクセスについて。

  3. ログテーブルに挿入する代わりに、syslog-ngのようなものを使用してそのような情報をログファイルに収集し(mysqlサーバーへの負荷がはるかに少なくなります)、生のテキストファイルからデータをmysqlに集約します(ここでは多くの選択肢があり、生をインポートすることもできます集計ルーチンに SQL の柔軟性が本当に必要な場合は、ファイルを mysql に戻します)。

それはそれについてです

于 2012-06-29T10:36:19.610 に答える