Как перевести и перенести данные - PullRequest
0 голосов
/ 21 сентября 2009

Я создаю веб-приложение php, которое позволяет пользователю загружать базу данных MS Access (csv export), которая затем переводится и переносится в базу данных MySQL.

База данных MS Access состоит из одной таблицы t_product из 100 тыс. Строк. Эта таблица не разработана хорошо. В качестве примера приведем следующий запрос:

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?

Ответы [ 3 ]

1 голос
/ 21 сентября 2009

Это может быть совсем не то направление, в котором вы хотите идти, но вы можете сгенерировать сценарий создания MySQL непосредственно из MS Access с помощью бесплатного MySQL Migration Toolkit

Возможно, вы могли бы разрешить пользователю загружать базу данных Access, а затем сделать так, чтобы ваш PHP-скрипт вызывал набор инструментов для миграции?

0 голосов
/ 22 сентября 2009

Я решил записать все свои запросы в файл .SQL. Это дало мне возможность нормализовать файл CSV в правильную реляционную базу данных. После этого мой php-скрипт называется exec ("mysql -h dbserver.com -u myuser -pmypass dbname

Это решило мои проблемы с памятью, и это было намного быстрее, чем несколько запросов от php.

0 голосов
/ 21 сентября 2009

Если вы собираетесь попробовать оптимизировать код, который у вас уже есть, я бы попытался объединить ВСТАВКИ и посмотреть, поможет ли это. Это должно быть легко добавить к вашему коду. Примерно так (псевдокод 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
...