0

我正在构建 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 数据库?

4

3 回答 3

1

这可能完全不是您想要的方向,但您可以使用免费的MySQL 迁移工具包直接从 MS Access 生成 MySQL 创建脚本

也许您可以允许用户上传 Access 数据库,然后让您的 PHP 脚本调用迁移工具包?

于 2009-09-21T17:57:05.080 回答
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
于 2009-09-21T18:44:13.113 回答
0

我决定将所有查询写入一个 .SQL 文件。这让我有机会将 CSV 文件规范化为适当的关系数据库。之后,我的 php 脚本调用了 exec("mysql -h dbserver.com -u myuser -pmypass dbname < db.sql");

这解决了我的内存问题,它比来自 php 的多个查询要快得多。

于 2009-09-22T02:28:57.317 回答