Есть ли лучшее решение, чем ActiveRecord для импорта пакетных данных? - PullRequest
3 голосов
/ 25 июня 2011

Я разработал веб-интерфейс для устаревшей (вендорной) базы данных с использованием Ruby on Rails.Схема базы данных представляет собой полный беспорядок,> 450 таблиц и данные клиентов, распределенные по более чем 20, включая сложные объединения и т. Д.

У меня есть хорошее решение для этого для веб-приложения, оно работает оченьЧто ж.Но мы также выполняем еженедельный импорт из внешних источников данных (в настоящее время просмотр базы данных SQL Server и SOAP-фида), и они запускаются в режиме SLOW.Около 1,5-2,5 часа для импорта данных XML и около 4 часов для импорта БД.

Это после выполнения некоторых основных оптимизаций, которые включают ручной запуск сборщика мусора MRI.И это прямо подсказывает мне, что я делаю это неправильно.Я рассмотрел перемещение ночных задач обновления / вставки из основного приложения Rails и попытался использовать JRuby или Rubinius, чтобы воспользоваться преимуществами лучшего параллелизма и сборки мусора.

Мой вопрос такой: я знаю ActiveRecordна самом деле не предназначен для этого типа задач.Но из вариантов O / RM для Ruby (мой любимый язык), похоже, лучшая поддержка Oracle.

Что бы вы сделали?Придерживаться AR и использовать другой переводчик?Это действительно поможет?А как насчет DataMapper или Sequel?Есть ли лучший способ сделать это?

Я открыт для использования Scala или Clojure, если есть лучшая альтернатива (не ограничиваясь, но это другие языки, на которых я сейчас играю) ... но я не хочу, чтобычто-то вроде DBI, где я пишу прямой SQL, если только по той причине, что обновления поставщика иногда меняют схему БД, и я бы предпочел изменить пару классов, а не сотни операторов UPDATE или INSERT.

Надеюсь, этот вопрос не «слишком расплывчатый», но я мог бы действительно воспользоваться некоторыми советами по этому вопросу.

FWIW, Ruby - 1.9.2, Rails - 3.0.7, платформа - OS X Server Snow Leopard (или дополнительно Debian 6.0).

Ответы [ 3 ]

2 голосов
/ 26 июня 2011

По моему опыту, ORM являются отличным инструментом для использования на внешнем интерфейсе, где вы в основном просто читаете данные или обновляете по одной строке за раз. На сервере, где вы принимаете потерянные данные одновременно, они могут вызвать проблемы из-за того, как они обычно взаимодействуют с базой данных.

В качестве примера предположим, что у вас есть объект Person с длинным списком друзей (скажем, на данный момент 100). Вы создаете объект Person и назначаете ему 100 друзей, а затем сохраняете его в базе данных. Обычно наивное использование ORM выполняет 101 запись в базу данных (по одной для каждого друга, по одному для человека). Если бы вы делали это в чистом SQL на более низком уровне, вы бы сделали 2 записи, одну для человека, а затем одну для всех друзей одновременно (вставка со 100 фактическими строками). Разница между этими двумя действиями значительна.

Есть несколько способов обойти эту проблему.

  • Используйте API базы данных более низкого уровня, который позволяет написать команду типа «вставьте 100 друзей за один вызов»
  • Используйте ORM, который позволяет писать SQL более низкого уровня, чтобы вставлять Friends в виде одной команды SQL (не все из них допускают это, и я не знаю, есть ли в Rails)
  • Используйте ORM, который позволяет выполнять пакетную запись в один вызов базы данных. Это все еще 101 запись в базу данных, но это позволяет ORM объединить их в один сетевой вызов базы данных и сказать «сделайте эти 101 вещь». Я не уверен, что ORM позволяют это.
  • Возможно, есть другие способы

Суть в том, что использование ORM для загрузки любого объема данных реального размера может привести к проблемам с эффективностью. Понимание того, что ORM делает изнутри (лучший способ понять, что он делает - попросить его записывать все вызовы БД) - лучший первый шаг. Как только вы поймете, что он делает, вы можете найти способы сказать ему: « то, что я делаю, плохо вписывается в обычный шаблон, давайте изменим способ его использования » ... и Если это не работает, вы можете использовать API более низкого уровня, чтобы учесть это.

Я укажу еще одну вещь, на которую вы можете посмотреть с СИЛЬНЫМ предостережением, что это должно быть одной из последних вещей, которые вы считаете. При массовом добавлении строк в базу данных можно создать необработанный текстовый файл со всеми данными (формат зависит от БД, но концепция аналогична CSV-файлу) и передать этот файл в базу данных для массового импорта. Это плохой путь почти во всех случаях, но я хотел включить его, потому что он существует как опция.

Редактировать : В качестве дополнительного примечания, комментарий о более эффективном синтаксическом анализе XML тоже стоит посмотреть. Использование SAX vs DOM или другой библиотеки XML может быть очень выигрышным во времени до завершения. В некоторых случаях это может быть даже более выигрышным, чем более эффективное взаимодействие с базой данных Например, вы можете анализировать много XML с большим количеством небольших фрагментов данных, а затем использовать только небольшие их части. В таком случае анализ может занять много времени через DOM, в то время как SAX может игнорировать части, которые вам не нужны ... или он может использовать много памяти для создания объектов DOM и замедлять все из-за мусора коллекция и т. д. По крайней мере, стоит посмотреть.

2 голосов
/ 26 июня 2011

Редактировать хорошо, только что понял, что это решение не будет работать для оракула, извините ---

Вы действительно должны проверить ActiveRecord-Import, он прост в использовании и обрабатывает массовый импорт с минимальным количеством SQL-операторов. Я видел скорость от 5 часов до 2 минут. И он все равно будет выполнять проверки данных.

со страницы github:

books = []
10.times do |i| 
    books << Book.new(:name => "book #{i}")
end
Book.import books

https://github.com/zdennis/activerecord-import

1 голос
/ 26 июня 2011

Поскольку ваш вопрос действительно "немного расплывчатый", я могу порекомендовать вам только оптимизировать импорт XML с помощью синтаксического анализа XML Pull.

Взгляните на это: https://gist.github.com/827475

Мне нужно было импортировать MySQL XML, и, честно говоря, использование метода XML Pull улучшило анализирующую часть примерно в 7 раз (да, почти в 7 раз быстрее, чем чтение всего в памяти).

Другое дело: вы говорите: «Импорт БД занимает 4 часа». В какие форматы файлов импортируются эти экспорты БД?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...