2012-04-12 85 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)可以是惊人的慢。