我正在构建php web应用程序,让用户上传MS Access数据库(csv导出),然后将其翻译并迁移到MySQL数据库中。
MS Access数据库由一个名为t_product(100k行)的表组成。这个表设计得不好。例如,以下查询:
SELECT part_number, model_number FROM t_product
将返回:
part_number model_number
100 AX1000, AX1001, AX1002
101 CZ10, CZ220, MB100
如您所见,型号列为逗号分隔值,而不是另一个表中的单个记录。还有更多这种性质的问题。我正在编写一个脚本来清理这些数据,然后再导入mysql数据库。该脚本还将现有的Access列映射到适当的关系设计数据库。
我的问题是我的脚本需要很长时间才能完成。这是解释我正在做什么的简化代码:
$handle = fopen("MSAccess.csv, "r");
// get each row from the csv
while ($data=fgetcsv($handle, 1000, ","))
{
mysql_query("INSERT INTO t_product (col1, col2 etc...) values ($data[0], $data[1], etc...");
$prodId = mysql_last_insert_id();
// using model as an example, there are other columns
// with csv values that need to be broken up
$arrModel = explode(',', $data[2]);
foreach($arrModel as $modelNumber)
mysql_query("INSERT INTO t_model (product_id, col1, col2 etc...) values ($prodId, $modelNumber[0], $modelNumber[1] etc...");
}
这里的问题是每个while循环迭代都会对数据库进行大量调用。对于每个产品记录,我必须插入N个型号,Y部件号,X序列号等......
我开始采用另一种方法将整个CSV存储在一个数组中。然后我写了一个批处理查询,如
$sql = "INSERT INTO t_product (col1, col2, etc...) values ";
foreach($arrParam as $val)
$sql .= " ($val[0], $val[1], $val[2]), "
但是我用这种方法遇到了过多的内存错误。我将最大内存限制增加到64M,而且我的内存仍然不足。
解决此问题的最佳方法是什么?
也许我应该首先将所有查询写入* .sql文件,然后将* .sql文件导入mysql数据库?
答案 0 :(得分:1)
这可能完全不是您想要的方向,但您可以使用免费的MySQL Migration Toolkit
直接从MS Access生成MySQL创建脚本也许您可以允许用户上传Access数据库,然后让您的PHP脚本调用Migration toolkit?
答案 1 :(得分:0)
如果您要尝试优化已经存在的代码,我会尝试聚合INSERTS,看看是否有帮助。这应该很容易添加到您的代码中。像这样的东西(C#伪代码):
int flushCount = 0;
while (!done)
{
// Build next query, concatenate to last set of queries
if (++flushCount == 5)
{
// Flush queries to database
// Reset query string to empty
flushCount = 0;
}
}
// Flush remaining queries to the database
答案 2 :(得分:0)
我决定将所有查询都写入.SQL文件。这使我有机会将CSV文件规范化为适当的关系数据库。之后,我的php脚本调用了一个exec(“mysql -h dbserver.com -u myuser -pmypass dbname< db.sql”);
这解决了我的内存问题,它比php的多个查询要快得多。