CSV-2-SQL

Posted: 2011-03-21 in IT, Software
Метки:

Итак, есть такая задача — перегрузить данные между разными базами данных. Причем совсем разными. Например, из DBF в MySQL. Или из древнего как говно мамонта Paradox (и совершенно уёбищно кривого) в MSSQL. Или из Cronos в PostgreSQL.

Несмотря на то, что принципы организации всех реляционных баз данных схожи, перенос данных может быть затруднен.
Основные проблемы тут такие:
1). Форматы данных. Во-первых, разные движки баз имеют разные наборы поддерживаемых форматов. Во-вторых, размерности полей. В третьих — типы хранения. Например, в DBF нет BLOB- и TEXT-полей, и впихать в поле DBF хоть что-нибудь длиннее 255 байт — невозможно в принципе, и это "в лоб" нерешаемо, ибо набор типов данных в DBF — весьма скуден. Даже при совпадении формата длина поля в целевой базе может оказаться короче, чем в исходной, что при наличии длинных строк вызовет либо обрезку содержимого этих строк, либо ошибки переноса данных, и менно поэтому надо провенрять, что поля типа VARCHAR либо имеют равную длину, либо самая длинная строка в исходном поле вмещается в поле целевой таблицы. Еще пример — перенос дат из какого-нить MSSQL, где в зависимости от кучи параметров словить дату можно в одном из двадцати форматов, и при подготовке процедур переноса данных за форматом даты надо внимательно следить, ибо невозможно "в лоб" сказать, что за момент времени обозначен записью '11.10.12' в том же M$-SQL.
2). Кодировки. Для текстовых строк в базе, содержащих не-английские символы, актуален вопрос кодировок в том случае, когда кодировки исходных и целевых таблиц не совпадают. Например, в DBF-файлах, которые так любят разработчеги из всяких Пенсионных Фондов и налоговых, кодировка текстовых полей — CP866 (времен старого доброго DOS). И при переносе данных возможны две ситуации — когда кодировку можно прозрачно конвертировать, и когда конвертировать кодировку нельзя. Так, если целевая база ожидает, что там будут данные в устаревших однобайтных кодировках — то вы туда никогда в жизни не сможете корректно залить данные, содержащие символы с умляутами, не говоря уже о китайских иероглифах.
3). Протоколы и средства взаимодействия. Тут ситуация вот в чем. Движков СУБД — довольно много, в том числе экзотических. И если мы хотим сделать любую из приведенных в начале выгрузок — то тут-то нас и поджидает вагон засад.

Рассмотрим конкретные примеры средств переноса между базами.
ODBC. Шикарная по сути идея. Проблема ровно в одном — во-первых, это всего лишь API, во-вторых — довольное кривое API, не рассчитанное к тому же на высокие нагрузки. Ни сто более-менее весомых выгрузок параллельно, ни одна выгрузка, но на 10Гб — неподъемны, драйвер ODBC умрет гораздо раньше, чем вы думаете. То есть мало того, что надо писать мини-приложение, так оно еще и нагрузку тянуть не будет. Тот, кто видел древний говнософт, юзающий ODBC — легко вспомнит, как подобной фигне хорошело при росте баз. Кроме того, оно до сих пор платформо-специфично, что сводит ценность оной фигни на нет.

Всякий софт от малоизвестных разработчегов. Тут мы наблюдаем "невинных авторов, жестоко угнетенных злобными пиратами, классический пример". Это именно те авторы, на которых так любят ссылаться копирасты всех мастей. Всяческие программы из серии CSV-2-SQL, DBF-2-MySQL, Access-2-MySQL, тысячи их. По цене 25-50$ за каждую. Вообще просить за ТАКОЕ денег — верх цинизма и наглости. А учитывая тот факт, что такие программы почти никогда не предоставляют путей решения вышеозначенных проблем (конверсия форматов, кодировки), то таких "разработчегов" мне лично ничуть не жалко. Я перепробовал кучу таких конвертеров. Мой вердикт — все подобные программы — совершенно непотребное сраное говно.

MS-DTS. Встроенное средство переноса данных в M$ SQL Server. Проблемы все те же и все там же — на тяжелых таблицах оно тупо выпадает, конвертировать кодировку на лету — хуй, и даже перенести уже собранный и подготовленный DTS-пакет на другой экземпляр SQL-сервера — тот еще секс с конями. Вообщем, все в лучших традициях M$, фича кагбе есть, но пользоваться невозможно.

Именно поэтому до сих пор основным реально рабочим методом для тяжелых дампов остается перенос данных через промежуточные файлы открытой структуры — через файлы с разделителями и формирование SQL-дампов в нужном синтаксисе.
Главное, чтобы из исходной базы можно было выгрузить данные в открытом формате с разделителями. После чего наш CSV-файл легко и непринужденно превращается в SQL-дамп
простейшим и красивым скриптом для sed :

# CSV 2 SQL    // SED
s/^/INSERT INTO `base`.`table1` VALUES ('/
s/$/');/
s/|/', '/g

И никаких денег говнокодерам. Суть — в трех заменах на каждую строку. В начало строки пишем кусочек инсерта, в конец строки — окончание, разделитель заменяем. Если в данных есть одиночные кавычки в строках — тот же sed легко сделает экранирование (s/'/\'/). Вообщем, это правило замены + sed перемалывает 800 Мб CSV в дамп для MySQL весом под 1,5 Гб буквально за полторы минуты. Никакой сраный говнософт "от угнетенных авторов" за 50$ и никакой сраный DTS даже близко не способны выдать нечто подобное. Да, кнопки "сделать пиздато" такая выгрузка не подразумевает. Зато и ситуацию, когда сраная говнософтень сперва три часа тормозит, а потом выпадает с глупой ошибкой нехватки памяти — тоже не подразумевает.
Выгрузки баз из Cronos в MySQL/PostgreSQL я делал именно таким методом — сперва в файл с разделителями (пара минут), потом конверсия SED-ом в SQL-дамп (1,5-2 миинуты), потом конверсия кодировки в UTF-8 (iconv, около минуты), потом заливка дампа (минут 15-20, самый долгий этап). Самое занятное — это был единственный реально работающий на таких базах способ, все остальное "не шмогло".

Для еще более жирных дампов (например, для MySQL) стоит пользовать LOAD DATA INFILE + файл исходных данных, подготовленный с помощью sed и iconv. А "мегапрограммы от угнетенных пиратами аффтаров" надо сбросить в биореактор вместе с аффтарами. Это ж охуеть — просить 25$ за функционал sed-скрипта в 80 байт весом.

- комментарии
  1. anonymous:

    alex writes:В postgresql есть команда COPYhttp://www.postgresql.org/docs/9.0/interactive/sql-copy.htmlА в принципе +100500

  2. xztque:

    +201000