Сценарий:
- Я загружаю некоторые данные в локальную базу данных MySQL каждый день, около 2 миллионов строк;
- Мне нужно ( иметь для - это вопрос аудита / регулирования) перейти на «правильно» администрируемый сервер, который в настоящее время выглядит как Oracle 10g;
- Сервер находится в другой стране: ток в оба конца сети занимает 60-70 мс;
- Входные данные - это файл CSV в денормализованной форме: я нормализую данные перед загрузкой, каждая строка обычно приводит к 3-8 вставкам в до 4 таблиц;
- Скрипт загрузки в настоящее время реализован на Ruby с использованием ActiveRecord и fastcsv. Я пробовал гем ar-extensions, но он предполагает, что идея предложения с несколькими значениями в стиле MySQL будет работать. Это не так.
РЕДАКТИРОВАТЬ : Очень полезные ответы уже - спасибо! Подробнее об этом надоедливом входном файле. Количество полей является переменным, и позиции менялись несколько раз - мой текущий скрипт определяет контент, анализируя строку заголовка (ну, более быстрый csv и хитрый конвертер делают это). Так что прямая загрузка и пост-обработка SQL не будет работать без нескольких версий загрузочного файла, что ужасно. Также это немецкий CSV-файл: разделенный точкой с запятой (ничего страшного) и десятичные дроби, обозначенные запятыми (довольно большая сделка, если мы не загрузим как VARCHAR и текстовый процесс потом - тьфу).
Проблема:
Загрузка 2 миллионов строк со скоростью около 7 / сек займет более 24 часов! Это может быть недостатком ежедневного процесса, не говоря уже о том, что пользователи скорее хотели бы иметь возможность доступа к данным через 5 часов после того, как они станут доступны в форме CSV!
Я смотрел на применение нескольких вставок за сетевое отключение: довольно неловкий синтаксис INSERT ALL...
был бы в порядке, за исключением того, что в настоящее время я применяю уникальный идентификатор для каждой строки, используя последовательность. Оказывается,
INSERT ALL
INTO tablea (id,b,c) VALUES (tablea_seq.nextval,1,2)
INTO tablea (id,b,c) VALUES (tablea_seq.nextval,3,4)
INTO tablea (id,b,c) VALUES (tablea_seq.nextval,5,6)
SELECT 1 FROM dual;
(я говорил, что это было неловко?) Пытается использовать один и тот же идентификатор для всех трех строк. Похоже, что Oracle подтверждает это.
Последняя попытка - отправить несколько INSERT за одно выполнение, например ::1010 *
INSERT INTO tablea (id,b,c) VALUES (tablea_seq.nextval,1,2);
INSERT INTO tablea (id,b,c) VALUES (tablea_seq.nextval,3,4);
INSERT INTO tablea (id,b,c) VALUES (tablea_seq.nextval,5,6);
Я не нашел способа убедить Оракула принять это.
Вопрос (ы)
- Я что-то упустил очевидное? (Я был бы , поэтому доволен, если бы это оказалось так!)
- Если я не могу отправить несколько вкладок, что еще можно попробовать?
Зачем это принимать?
По какой-то причине я предпочитаю сохранять свой код максимально свободным от платформо-зависимых конструкций: одна из причин, по которой возникла эта проблема, заключается в том, что я перехожу с MySQL на Oracle; Вполне возможно, что однажды может произойти еще один шаг по географическим причинам, и я не могу быть уверен в платформе. Поэтому доведение моей библиотеки базы данных до такой степени, что она может использовать текстовую SQL-команду для достижения разумного масштабирования, было привлекательным, и блок PL / SQL выполняет это. Теперь, если появится другая платформа, изменение будет ограничено заменой адаптера в коде: по всей вероятности, одной строкой.