2

行をテーブルに挿入するループが PHP コードに含まれています。例えば:

while ($info = mysql_fetch_assoc($someQuery)) {
    mysql_query("INSERT INTO X (i,j) VALUES ($info['ii'],$info['jj'])");
}

ループは数回しか繰り返されないため、数か月前はこれで問題ありませんでした。ただし、Web サイトのトラフィックが増加したため、このループが 1000 回以上繰り返されることがあります。テーブルにはいくらかのオーバーヘッド( 4,305 KiB ) があり、このテーブルからの SELECT がMySQL のスローログに表示されています。これはおそらく、INSERT の長いリストがロックを解放するのを待たなければならないためですか?

スケーリングを改善するには、コードをどのように最適化すればよいですか?

私が試してみようと思ったいくつかのこと:

  • INSERT DELAYED - 調べる必要があります。役に立ちますか?
  • 同じクエリに複数の行を挿入してみてください。しかし、どのような制限を設定する必要がありますか? 50、500、1000?
4

6 に答える 6

7

$someQueryとは? INSERT ... SELECT構文を使用できますか?

于 2010-01-28T10:33:11.407 に答える
4

繰り返す代わりに、準備済みステートメントmysql_query()を使用します。これらは、同じクエリを異なる値で何度も繰り返すためのはるかに効率的な方法です。

また、スローログに表示されているクエリも調べます。EXPLAIN (<query>)インデックスが使用されていることを確認するために使用します。

于 2010-01-28T10:31:16.360 に答える
4

次のようなステートメントを作成することもできます。

INSERT INTO X (i,j)
VALUES ($info['ii'],$info['jj']),
(val, val),
...
(val, val);

SQL が長くなりすぎる場所を特定するために、さまざまな制限を試すことができます。次に、制限を適切なものに設定できます。

于 2010-01-28T11:00:35.540 に答える
2

MySQL にデータを取得する最速の方法の 1 つは、LOAD DATA INFILE. CSV インポートと考えてください。一度に 1 行ずつデータをディスクに書き込んでから、一括読み込みを行うことができます。このページに よると、挿入速度LOAD DATA INFILEはストレートよりも 20 倍高速ですINSERT

ただし、一度に 1 行だけではなく、プロセス全体でテーブルがロックされる可能性があるため、望ましくない副作用が他にもある可能性があります。これをたとえば100行のバッチで実行すると、問題の両方の部分が管理しやすくなる可能性があります-実験する必要があるだけだと思います.

于 2010-01-28T11:18:09.140 に答える
2

ベン・ジェームズが言ったことは重要です。同じ SQL を実行し、その中のパラメーターを変更するだけで、準備済みステートメントははるかに高速になります。

また、ループ全体を次のように変更しようとしています。

INSERT INTO x (i, j) SELECT (here goes your $someQuery)

もちろん、$someQuery を調整する必要があるため、列 i および j と同じ型 (または自動的にキャストできる) の 2 つの列のみを選択します。

PHP に非常に複雑なメカニズムがない場合は、このシュラウドが可能であり、どの PHP ループよりもはるかに高速です。

于 2010-01-28T10:38:48.417 に答える
1

新しいバージョンの MySQL には、ストアド プロシージャと関数があります。そこでは、変数、ループ、および条件付きブロックを含む構造化言語を使用できます。1 つのストアド プロシージャは、多数の独立した挿入よりも高速である必要があります。しかし、それは学ぶべき新しい言語です。

ストアド プロシージャを使用するには、php に mysqli 拡張機能が必要です。

mysqli_multi_query も参照できます。
http://pl.php.net/manual/en/mysqli.multi-query.php

于 2010-01-28T21:36:31.410 に答える