Какой самый быстрый способ загрузить файл XML в MySQL с помощью C #? - PullRequest
12 голосов
/ 21 сентября 2009

Вопрос

Какой самый быстрый способ вывести большой (> 1 ГБ) XML-файл в базу данных MySQL?

Данные

Данные - это дамп данных Creative Commons StackOverflow.

Назначение

Это будет использоваться в автономной программе просмотра StackOverflow, которую я создаю, так как я хочу заняться изучением / программированием в местах, где у меня не будет доступа к Интернету.

Я хотел бы сообщить об этом остальным членам StackOverflow для собственного использования после завершения проекта.

Задача

Первоначально я читал из XML / записывал в БД по одной записи за раз. Это заняло около 10 часов, чтобы запустить на моей машине. Используемый мной хакерский код теперь выбрасывает 500 записей в массив, а затем создает запрос вставки для загрузки всех 500 одновременно (например, "INSERT INTO posts VALUES (...), (...), (...) ... ;"). В то время как это быстрее, все еще требуются часы, чтобы бежать. Ясно, что это не лучший способ, поэтому я надеюсь, что большие мозги на этом сайте узнают о лучшем способе.

Ограничения

  • Я создаю приложение, используя C # в качестве настольного приложения (т.е. WinForms).
  • Я использую MySQL 5.1 в качестве базы данных. Это означает, что такие функции, как "LOAD XML INFILE filename.xml", не могут использоваться в этом проекте, поскольку эта функция доступна только в MySQL 5.4 и выше. Это ограничение во многом связано с моей надеждой на то, что проект будет полезен для других людей, кроме меня, и я бы не стал заставлять людей использовать бета-версии MySQL.
  • Я бы хотел, чтобы загрузка данных была встроена в мое приложение (т. Е. Нет инструкций для "Загрузите дамп в MySQL с помощью 'foo' перед запуском этого приложения.").
  • Я использую MySQL, Connector / Net, поэтому все в пространстве имен MySql.Data является приемлемым.

Спасибо за любые указатели, которые вы можете предоставить!


Идеи пока что

хранимая процедура, которая загружает весь XML-файл в столбец, а затем анализирует его, используя XPath

  • Это не сработало, поскольку размер файла подчиняется ограничениям переменной max_allowed_packet, для которой по умолчанию установлено значение 1 МБ. Это намного меньше размера файлов дампа данных.

Ответы [ 8 ]

12 голосов
/ 24 сентября 2009

Есть 2 части к этому:

  • чтение XML-файла
  • запись в базу данных

Для чтения XML-файла, эта ссылка http://csharptutorial.blogspot.com/2006/10/reading-xml-fast.html показывает, что 1 МБ можно прочитать за 2,4 секунды с использованием потокового считывателя, что будет 2400 секунд или 40 минут (если мои математические операции работают так поздно) Файл 1 ГБ.

Из того, что я прочитал, самый быстрый способ получить данные в MySQL - это использовать LOAD DATA.

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

Поэтому, если вы можете прочитать данные xml, запишите их в файлы, которые могут быть использованы LOAD DATA, а затем запустите LOAD DATA. Общее время может быть меньше, чем часы, которые вы испытываете.

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

SqlBulkCopy ROCKS. Я использовал его, чтобы включить функцию 30 минут до 4 секунд. Однако это применимо только к MS SQL Server .

Могу ли я предложить вам взглянуть на ограничения на вашей таблице, которую вы создали? Если вы отбросите все ключи в базе данных, ограничения и т. Д., База данных будет выполнять меньше работы над вашими вставками и меньше рекурсивной работы.

Во-вторых, настройте таблицы с большими начальными размерами, чтобы предотвратить изменение размеров при вставке в пустую базу данных.

Наконец, посмотрите, есть ли API для массового копирования для MySQL. SQL Server в основном форматирует данные так, как будто они записываются на диск, а SQL-сервер связывает поток с диском, и вы вводите данные. Затем он выполняет одну проверку непротиворечивости для всех данных вместо одной на вставку, что значительно повышает вашу производительность. Удачи;)

Вам нужен MySQL? SQL Server делает вашу жизнь проще, если вы используете Visual Studio и ваша база данных имеет низкую производительность / размер.

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

У меня есть несколько мыслей, которые помогут ускорить это ...

  1. Размер запроса может быть изменен, часто возникает момент, когда большой оператор стоит больше времени на разбор и поэтому становится медленнее. 500 может быть оптимальным, но, возможно, это не так, и вы можете немного подправить (это может быть больше, может быть меньше).

  2. Перейти многопоточным. Предполагая, что ваша система еще не ограничена обработкой, вы можете получить некоторые преимущества, разбив данные на куски и обработав их потоками. Опять же, это экспериментально, чтобы найти оптимальное количество потоков, но многие люди используют многоядерные машины и имеют запасные циклы ЦП.

  3. В области базы данных убедитесь, что таблица настолько проста, насколько это возможно. Отключите все индексы и загрузите данные перед их индексацией.

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

Хорошо, я собираюсь быть идиотом и ответить на ваш вопрос вопросом.

Зачем помещать его в базу данных?

Что если ... просто что-если ... вы записали xml в файлы на локальном диске и, если необходимо, запишите некоторую информацию об индексировании в базу данных. Это должно выполняться значительно быстрее, чем при попытке загрузить базу данных, и будет гораздо более переносимым. Все, что вам нужно, это способ поиска и индексирования реляционных ссылок. Там должно быть много помощи с поиском, и реляционный аспект должен быть достаточно легко построить? Вы можете даже подумать о переписывании информации, чтобы каждый файл содержал один пост со всеми ответами и комментариями.

Во всяком случае, только мои два цента (и это не стоит ни копейки).

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

В PostgreSQL , самый быстрый способ получить объемные данные - отбросить все индексы и триггеры, использовать эквивалент MySQL LOAD DATA , а затем заново создать ваши индексы / триггеры. Я использую эту технику для загрузки 5 ГБ данных форума в базу данных PostgreSQL примерно за 10 минут.

Конечно, это может не относиться к MySQL, но оно того стоит. Кроме того, ответ на этот вопрос SO предполагает, что это фактически жизнеспособная стратегия для MySQL.

Быстрый Google нашел несколько советов по повышению производительности MySQL LOAD DATA .

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

Я заметил в одном из ваших комментариев выше, что вы рассматриваете MSSQL, поэтому я решил опубликовать это. В SQL Server есть утилита SQMLXMLBulkLoad, предназначенная для импорта больших объемов данных XML в базу данных SQL Server. Вот документация для версии SQL Sever 2008:

http://msdn.microsoft.com/en-us/library/ms171993.aspx

Более ранние версии SQL Server также имеют эту утилиту

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

Не тот ответ, который вам нужен, но mysql c api имеет функцию mysql_stmt_send_long_data .

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

это помогает вообще? Это хранимая процедура, которая загружает весь XML-файл в столбец, затем анализирует его с помощью XPath и создает таблицу / вставляет данные оттуда. Кажется сумасшедшим, но это может сработать.

...