【问题标题】:Mysql multi-table Insert about 8k recordsMysql多表插入约8k条记录
【发布时间】:2015-07-01 14:05:40
【问题描述】:

我有一个包含大约 8k 条记录的临时表(旧系统的转储,一长行包含许多详细信息),我需要将其分解,使用一些逻辑并将数据插入 3 个不同的表中。

table_temp (id, name, address, email, phone, mobile, etc......)
tbluser (id, username, password, roleid, status)
tblstudent (id, userid, name, address, classid, sectionid, etc.....)
tblstudentdetails(id, studentid, address, contact details....)

由于我需要获取数据,因此请为所有这些表添加一些逻辑并创建单独的插入语句。我试图创建大型插入语句,例如:

INSERT INTO `tbluser`(`instsessassocid`, `username`, `password`, `roleid`, `status`) VALUES 
('1','PRAGUN10000@temp.com','$2y10$gFscDWwWKR8Iven6R','3','1'),
('1','SONAM10001@temp.com','$2y10$gFscDWwWKR8Iven6R','3','1'), 
('1','SONAM10001@temp.com','$2y10$gFscDWwWKR8Iven6R','3','1')

其他表格也一样(你懂的):

INSERT INTO `tblstudent`(`scholarnumber`,`firstname`, `middlename`,`lastname`) VALUES
('10000','PRAGUN','','TANWAR'),('10001','SONAM','','-'),
('10002','HITESH','','KUMAR'),('10003','KHUSHI','','MEHTA'),
('10004','ADITYA','','VASYANI')

创建 4 个大型插入语句后,我将它们存储在一个数组中并将其发送到我的插入函数,该函数推迟自动提交,接受每个插入语句,一旦一切正常,提交并返回插入 ID 等。

我的应用程序似乎超时(当前设置为默认/30 秒),这么小的插入肯定不应该超时,谁能指出我做错了什么或如何改进。

这是我的插入函数:

function dbInsert($sql) {
    if (is_array($sql) == 0) {
       $sqlarray[] = $sql;
        } else {
            $sqlarray = $sql;
        }
        $sqlCount = count($sqlarray); //echoThis($sqlCount); die;
        $con = dbConnect();
        $insertID = array();
        try {
            // begin a transaction
            $con->autocommit(FALSE);
            /* commit transaction */

            foreach ($sqlarray as $value) {

                if ($con->query($value)) {
                    $insertID[] = $con->insert_id;
                } else {
                    trigger_error(mysqli_error($con));
                }
            }
            // if no error, commit.
            if ((!mysqli_error($con)) || (!mysqli_commit($con)) && ($sqlCount === count($insertID))) {
                $con->commit(); //mysqli_commit($con);
            } else {
                $con->rollback();
                trigger_error("Error in dbInsert: " . mysqli_error_list($con));
                $con->close();
            }
        } catch (Exception $e) {
            // if any error, catch the exception and rollback 
            $con->rollback();
            trigger_error("Error in dbInsert:" . $e);
        }
        /* close connection and return the result */
        $con->close();
        return $insertID;
    }

这只是一个测试,一旦排序,我需要导入相当多的记录,所以我想要有“准备好的脚本”,我可以根据需要使用它们。

我知道加载 infile 或 mysqlimport 方式,但我需要逻辑,我真的认为我的脚本应该能够完成这项工作。请注意,我在我的本地主机上,合理的配置机器没有其他任何事情发生。

谢谢!

【问题讨论】:

  • 您使用的是 MyIsam 表还是 Innodb? Innodb 支持事务,但导入速度相当慢。如果要计算执行时间,可以尝试导入少量行并获取操作前后的时间戳。完成后,计算脚本需要多长时间是一件小事
  • @Osuwariboy,我正在使用 innodb。是的,我可以把它分解成更小的脚本。但是,大约 3k 条记录(这是一组插入的记录)应该超时吗?我正在做的事情有什么严重的错误,或者它就是这样吗?谢谢大家!

标签: php mysqli insert


【解决方案1】:

您所做的似乎没有任何本质上的错误。但是,根据您告诉我的情况,数据已经在单行的表中。所以也许你可以让 MySQL 代替 PHP 为你做逻辑。这就是我的意思:

1) 根据需要向第一个临时表添加尽可能多的字段,以便您有足够的空间接收所需的信息

2) 这是一个解决方案,可以让您使用给定的分隔符分割字符串:

Split value from one field to two

你在这里做的是这样的查询

UPDATE myTable
SET newField1 = SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1),
newField2 = SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1),
....

最后,您想要的是将数据拆分为所有不同的字段,而不仅仅是一个大字段。

4) 最后,你可以这样做:

INSERT INTO tbluser 
SELECT field1, field2, field3 FROM myTable

一旦数据在适当的表中,您就可以运行一系列更新来修复使数据适合生产所需的任何逻辑。我不知道这是否会比批量插入更快,但我认为值得一试。

【讨论】:

  • 谢谢。实际上,我需要拆分数据,从不同的表中获取新的 id(通过 select 语句)并相应地插入到 3 个表中。我注意到我可以插入大约 456 条记录,然后它就会超时。我确实尝试将数据写入 csv 文件并执行 mysqlimport。但是如果能够通过 php+mysql 做到这一点会很好,因为我需要导入相当多的数据。我很惊讶它无法处理这个问题,但我不知道如何改进它。有趣的是,ms access 似乎做得更快。不过谢谢你的帮助!
  • 您知道,如果这些表都是临时的,您可以将它们创建为 MyIsam,然后执行更改表将它们转换为 Innodb。此外,当表具有索引字段时,Innodb 的速度会大大降低。也许您可以在加载数据后尝试创建表并放置索引。
  • 谢谢@Osuwariboy,我会试试的。然而,现在我每次将记录集限制在大约 500 个;它看起来更长,但我能够根据需要导入所有数据。再次感谢!
猜你喜欢
  • 2012-12-16
  • 2012-09-24
  • 2014-04-22
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 2016-09-01
  • 1970-01-01
相关资源
最近更新 更多