0

私は、ユーザーが MS Access データベース (csv エクスポート) をアップロードし、それを変換して MySQL データベースに移行できるようにする php Web アプリケーションを構築しています。

MS Access データベースは、100k 行の t_product と呼ばれる 1 つのテーブルで構成されています。このテーブルはうまく設計されていません。例として、次のクエリを実行します。

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 全体を配列に格納する別のアプローチを開始しました。次に、次のような 1 つのバッチ クエリを記述します。

$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

これは完全にあなたが行きたい方向ではないかもしれませんが、無料のMySQLMigrationToolkitを使用してMSAccessから直接MySQL作成スクリプトを生成することができます

おそらく、ユーザーにAccess dbのアップロードを許可してから、PHPスクリプトに移行ツールキットを呼び出させることができますか?

于 2009-09-21T17:57:05.080 に答える
0

すべてのクエリを.SQLファイルに書き込むことにしました。これにより、CSVファイルを適切なリレーショナルデータベースに正規化する機会が得られました。その後、私のphpスクリプトはexec( "mysql -h dbserver.com -u myuser -pmypass dbname <db.sql");と呼ばれました。

これは私のメモリの問題を解決し、phpからの複数のクエリよりもはるかに高速でした。

于 2009-09-22T02:28:57.317 に答える
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 に答える