0

基本的にページでのユーザーアクションを記録するMySQLテーブルに次のデータ構造があります

id int
page_id int
user_id int
action_type enum(6)
date_created datetime`

次のインデックスがあります。

id Primary key
user_id-page_id-date_created unique
page_id-user_id-date_created
user_id
page_id-date_created

問題は、このテーブルには現在 1 億 2500 万行あり、1 日あたり 80 万行の割合で増加しているため、挿入が完了するまでに約 2 時間かかることです。挿入は、他の 3 つのテーブルからデータを選択する 3 つのクエリによって行われます。今回は何を改善できるでしょうか?mysql をやめて、他のデータベース ソリューションを試す必要がありますか?

LE:あなたのフィードバックに基づいて、私はより多くの情報を提供しようとしています. まず、テーブルは MyISAM であり、これらの挿入は cron ジョブで毎晩 1 回行われ、テーブルからデータを削除することはありません。これが私がインサートを処理する方法です。大きなテーブルを big_table と呼び、3 つのテーブルはそれぞれ構造が似ているので content_table とします。説明は、約 1 億 850 万の 3 つのテーブルのうち最大のものになります。最初に、php を使用して挿入を開始する ID を取得します。(インデックスなしのクエリが取得するのに3分かかります)

SELECT id FROM content_table WHERE date_created > "2012-04-18" ORDER BY id ASC LIMIT 1;
+-----------+
| id        |
+-----------+
| 107278872 |
+-----------+
1 row in set (3 min 15.52 sec)

EXPLAIN SELECT id FROM content_table WHERE date_created > "2012-04-18" ORDER BY id ASC LIMIT 1;
+----+-------------+------------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table            | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+------------------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | content_table    | index | NULL          | PRIMARY | 4       | NULL |    1 | Using where |
+----+-------------+------------------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.06 sec)

そして、このIDを使用して、次のことを行います

INSERT IGNORE INTO big_table (user_id, page_id, type, date_created) 
SELECT user_id, page_id, IF (is_admin,"admin_action","action") as type, created_time FROM content_table WHERE id >= "107278872";

選択の説明は次のようになります

EXPLAIN SELECT user_id, page_id, IF (is_admin,"admin_action","action") as type, created_time FROM content_table WHERE id >= "107278872";
+----+-------------+------------------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table            | type  | possible_keys | key     | key_len | ref  | rows   | Extra       |
+----+-------------+------------------+-------+---------------+---------+---------+------+--------+-------------+
|  1 | SIMPLE      | content_table    | range | PRIMARY       | PRIMARY | 4       | NULL | 777864 | Using where |
+----+-------------+------------------+-------+---------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)

私もphpmyadminで試してみたところ、約0.004秒の時間が得られたので、データのフェッチではなく挿入に時間がかかると思います。サーバーについて私が知っているのは、それがクアッドコア xeon @ 2.4 ghz と 16 GB の RAM であることだけですが、ストレージについては何も知りません (その情報が得られたらすぐに戻ってきます)。また、データはロギングには使用されませんが、どのユーザーがページで最もアクティブであったか、さまざまなグループ化などの統計が必要であり、ユーザーはこれらの間隔を指定できます。

4

3 に答える 3

3

あなたは出来る:

  1. 他の 3 つのテーブルで実行するクエリで EXPLAIN PLAN を実行して、適切にインデックスが作成されているかどうかを確認します。TABLE SCAN を排除する必要があります。
  2. クエリの WHERE 句ごとに、これら 3 つの他のテーブルにインデックスを追加します。
  3. 日、週、月、またはその他の適切なメカニズムでデータを分割して、最も古いデータをレポート/ウェアハウス ソリューションに移動できるようにします。
  4. トリガー ソリューションが役立つかどうかを確認できます。
  5. データベースのプロファイルを作成し、ネットワーク トラフィックを監視して、どこで時間が費やされているかを確認します。

すべてのリレーショナル データベースは、大量のデータを処理しなければならないことに悩まされます。最初に考えるべきは、MySQL をドロップすることではありません。アーカイブ戦略に必要なものを把握する必要があります。特定の時点でトランザクション ストアに必要なデータの量を正確に決定する必要があります。

于 2012-04-18T12:05:46.150 に答える
0

インサートに影響を与える要因はたくさんあります。

  • エンジン型式
  • インデックス
  • データの挿入方法など。

まず、データの挿入方法を教えてください。次に、ストレージエンジンがテーブルに使用していることを教えてください。次に、挿入クエリをさらに最適化できます。一般に、不要なインデックスは挿入速度が遅いことを意味します。

挿入速度の詳細については、dev.mysqlのこの記事を読んで挿入速度を確認してください。

于 2012-04-18T12:15:13.883 に答える
0

それらをどのように挿入していますか?このようなループ クエリを 1 秒あたり特定の数のトランザクションしか持つことができません

//start loop
insert into table values (1) 
//end loop

よりもはるかに遅くなります

//start loop
//fill a variable 
//end loop
insert into table values (1),(2),(3),(4) // where (1),(2),(3),(4) are values filled by the loop

(このようにあまりにも多くの値を挿入することはできないことに注意してください。データで試してみてください。通常、200程度がかなり良い値です)

あなたは大量のインデックスを持っていないので、それらが問題を引き起こしているとは思わない.

于 2013-06-27T21:39:21.813 に答える