2012-04-12 15 views
1

いくつかの複雑なデータをmysqlデータベースに挿入しようとしましたが、実装のパフォーマンスに問題があります。私は私がデータベースに挿入するデータの全体の束を受け取り、私のデータベース内のテーブル3複雑なデータを効率的に挿入mysql

users columns[userid, name,...] 
questions columns[questionid, userid, questiontext] 
answers columns[answerid, questionid, answertext] 

を定義し、このため

user1 
    question1_1 
    answer1_1_1 
    answer1_1_2 
    answer1_1_3 
    ... 
    question1_2 
    answer1_2_1 
    answer1_2_2 
    ... 
    ... 
user 2 
... 

:私のデータは次のようになります。テーブルがリンクされているので、ユーザーを挿入してIDを取得し、質問にVALUESを使用する実装があります。これは動作しますが、「最大実行時間30秒を超えました」は、 mysqlは文を挿入します。

私の現在のコードは次のようになります。

for ($i=0; $i<sizeof($users); $i++) 
{ 
    $user = $users[$i]; 
    $sqlstr = "INSERT INTO users (username) VALUES ('".$users[$i]->id."')"; 

    mysql_query($sqlstr); 
    $userid = mysql_insert_id(); 

    for ($j=0; $j<sizeof($user->question); $j++) 
    { 
    $question = $user->question[$j]; 

    $sqlstr = "INSERT INTO question (userid,creator,date) VALUES (".$userid.",'".$question->creator."','".$question->date."')"; 

    mysql_query($sqlstr); 
    $questionid = mysql_insert_id(); 

    $rows = array(); 
    $sqlstr = "INSERT INTO answers (questionid,name,value) VALUES "; 
    for ($k=0; $k<sizeof($question->answers); $k++) 
    { 
     $rows[] = "('".$questionid."','".$question->answers[$k]->name."','".$question->answers[$k]->value."')"; 
    } 
    $sqlstr = $sqlstr.implode(',',$rows); 
    mysql_query($sqlstr); 
    } 
}  

は、どのように私は、以前のインサートのIDは、次のINSERT文で使用されていることを考えると、一つの大きなstatementmに別のINSERT文を組み合わせることができますか?私はLAST_INSERT_ID()で実験しましたが、期待どおりに動作しません。そのテーブルの最後のIDを参照しているようです。

他の解決方法がありますか?

+0

'LAST_INSERT_ID()'は、挿入されたテーブルに関係なく、挿入された最後の行のIDを返す必要があります。あなたがそれに問題があるなら、おそらく間違った順序であなたの声明を持っているでしょう。単一のステートメント(AFAIK)で複数のテーブルに挿入することはできませんが、MySQL [UDF](http://dev.mysql.com/doc/refman/5.1/ja/adding-udf.html)をそれをやる。非常に長時間実行されているPHPスクリプトをお持ちの場合は、 'set_time_limit(0);'を忘れないでください。 – DaveRandom

+0

質問に現在のPHPコードを追加してください。 – nnichols

+0

@DaveRandomあなたが正しいです。私は 'LAST_INSERT_ID'と間違えてしまったが、私のコードを最適化するためにはまだ役に立たない。 @nnichols私の現在の低速コードを追加しました – Tin

答えて

1

トランザクション内でSQL文をラップすることができます。 dev.mysql.com/doc を参照してください。これにより、データベースの充填が高速化される一方で、小さな単一の挿入文を発行し続けることが可能になります。

トランザクションを開始すると、コミットするまですべてのディスクアクセスが一時停止されます。これは、すべてのインサートが一度にディスクに書き込まれることを意味します。また、すべてのハウスキーピング更新は、一度だけ書き込まれる必要があります。

mysql_query('START TRANSACTION'); 
<your code> 
mysql_query('COMMIT'); 

:(ROLLBACKを使用して)トランザクションをアボートは驚くほど遅いことができます。

関連する問題