2012-04-12 99 views
1

我嘗試將一些複雜的數據插入到mysql數據庫中,但是我遇到了執行性能問題。我的數據是這樣的:複雜數據的高效插入mysql

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

對於這個定義我在我的數據庫3個表

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

我收到的數據一大堆,我想要插入到數據庫中。因爲這些表是鏈接的,所以我現在有一個插入用戶的實現,檢索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); 
    } 
}  

我如何可以結合不同的插入語句變成一個大statementm,因爲以前的插件的ID在接下來的INSERT語句使用?我用LAST_INSERT_ID()進行了實驗,但是這不能按預期工作。它似乎引用了該表的最後一個ID。

或者有可能是另一種解決方案?

+0

'LAST_INSERT_ID()'應該返回插入的最後一行的ID,而不管它被插入到哪個表中。如果您遇到問題,您可能會以錯誤的順序收到您的陳述。無法在單個語句(AFAIK)中插入多個表,但可以寫一個MySQL [UDF](http://dev.mysql.com/doc/refman/5.1/en/adding-udf.html)到做到這一點。不要忘了你可以'set_time_limit(0);'如果你有一個非常長的PHP腳本。 – DaveRandom 2012-04-12 17:16:05

+0

請將您當前的PHP代碼添加到您的問題中。 – nnichols 2012-04-12 17:23:38

+0

@DaveRandom你說得對。我用'LAST_INSERT_ID'弄錯了,但對於優化我的代碼仍然沒用。 @nnichols我加了我目前的慢代碼 – Tin 2012-04-12 18:10:17

回答

1

您可以將sql語句包裝在一個事務中。請參閱dev.mysql.com/doc 這可能會加快填充數據庫的速度,同時仍然允許您繼續發佈小型單插入語句。

當您開始一個事務時,所有的磁盤訪問都會暫停,直到您提交。這意味着您的所有插入將一次寫入磁盤。此外,所有的管家更新只需要寫一次。

例如

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

:中止交易(使用ROLLBACK)可以是驚人的慢。