Доброе время суток.Передо мной вставала задача написать класс,который инсертит много(1000-10000) записей в таблицу Oracle.
Подскажите как лучше всего реализовать?
Здравствуйте, o_x_y, Вы писали:
__>Доброе время суток.Передо мной вставала задача написать класс,который инсертит много(1000-10000) записей в таблицу Oracle. __>Подскажите как лучше всего реализовать?
Здравствуйте, Trean, Вы писали:
T>Здравствуйте, o_x_y, Вы писали:
__>>Доброе время суток.Передо мной вставала задача написать класс,который инсертит много(1000-10000) записей в таблицу Oracle. __>>Подскажите как лучше всего реализовать?
T>http://java.sun.com/docs/books/tutorial/jdbc/jdbc2dot0/batchupdates.html
T>Оно?
Есть такое мнение, что инсерт используя preparestatement тоже ускоряет данное действие, действительно ли это так? Если есть специались по Oracle — jdbc — java, то хочется услышать мнение, какой метод наиболее действенный, как лучше делать и почему
Здравствуйте, Sahivi, Вы писали: S>Есть такое мнение, что инсерт используя preparestatement тоже ускоряет данное действие, действительно ли это так? Если есть специались по Oracle — jdbc — java, то хочется услышать мнение, какой метод наиболее действенный, как лучше делать и почему
IMHO,
1) use batch updates
2) use prepared statemetns
3) disable indices before starting batch execution; enable them back at the finish.
Наиболее действенный — именно batch (array binding еще называется в Оракловой документации).
Потому что одним запросом на сервер отправляешь сразу кучу строк (скажем, 10 000).
Здравствуйте, Igor Trofimov, Вы писали:
iT>Наиболее действенный — именно batch (array binding еще называется в Оракловой документации). iT>Потому что одним запросом на сервер отправляешь сразу кучу строк (скажем, 10 000).
Нужно ли использовать prepareStatement или обычный Statement в коде? есть ли какой плюс от prepareStatement в данном случае?
Здравствуйте, Sahivi, Вы писали: S>Нужно ли использовать prepareStatement или обычный Statement в коде? есть ли какой плюс от prepareStatement в данном случае?
Нужно. Потому что в случае prepared statement сам запрос парсится компилируется только один раз, а затем используется многократно с разным набором параметров. А если просто statement — то разбор и компиляция будет проходить на каждом из 10000 (или сколько там?) инсертов.
Здравствуйте, ika, Вы писали:
ika>Здравствуйте, Sahivi, Вы писали: S>>Есть такое мнение, что инсерт используя preparestatement тоже ускоряет данное действие, действительно ли это так? Если есть специались по Oracle — jdbc — java, то хочется услышать мнение, какой метод наиболее действенный, как лучше делать и почему ika>IMHO, ika>1) use batch updates ika>2) use prepared statemetns ika>3) disable indices before starting batch execution; enable them back at the finish.
Здравствуйте, Sahivi, Вы писали: ika>>2) use prepared statemetns ika>>3) disable indices before starting batch execution; enable them back at the finish. S>про 3 пункт можно поподробнее?
Конечно можно. Есть таблица, в ней (весьма вероятно) пачка индексов. Когда вставляется запись, все они перестраиваются с учетом добавленной записи. Очевидно, что раз выгодней запустить такую перестройку только один раз вместо тысячи. Именно по этому я думаю и было бы полезно временно отключить индексы (или дропнуть вобще их). Когда они в конце даталоада будут восстановлены, они будут построены по последним даннгым, имеющимся в таблице.
ЗЫ: если на таблице есть триггеры, то отключать индексы нельзя (скорей всего перфоманс упадет, нужно смотреть что там за триггеры и что за индексы).
ЗЫ2: уменя нет точных метрик для сравнения. совет даю исключительно из интуитивных предположений и своих теоретичиских знаний.
...добавлю: изыски типа отключения индексов не рекомендуется применять, если во время загрузки данных возможны параллельные обращения к таблице для чтения этих данных. Иначе каждый запрос при отсутствии индексов будет производить table full scan, что будет как сервер загружать зазря, так и работать медленно.
S>>Нужно ли использовать prepareStatement или обычный Statement в коде? есть ли какой плюс от prepareStatement в данном случае?
Протестируй. Но если у тебя всего тысяч сто записей — то может уже и не обязательно.
ika>Нужно. Потому что в случае prepared statement сам запрос парсится компилируется только один раз, а затем используется многократно с разным набором параметров. А если просто statement — то разбор и компиляция будет проходить на каждом из 10000 (или сколько там?) инсертов.
Мне кажется, в случае с array binding это неверно. Серверу достоверно известно, что нужно один и тот же sql-оператор выполнить над кучей параметров. Да еще как атомарное действие. С чего это он будет на каждый набор параметров перепарсивать запрос??? Очень сомнительно.
Здравствуйте, Igor Trofimov, Вы писали:
S>>>Нужно ли использовать prepareStatement или обычный Statement в коде? есть ли какой плюс от prepareStatement в данном случае?
iT>Протестируй. Но если у тебя всего тысяч сто записей — то может уже и не обязательно.
В свое время я проверял для выборки:
Выборка 4-х полей с 3-я параметрами из 1 000 000 записей
для Statement усредненное время 1-й выборки составило 30ms
для PreparedStatement на 1 ms меньше.
Понятно что данные относительны для конкретного компа, но тем не менее умножаем на 100 000 циклов и имеем конкретный ощутимый результат.
iT>Мне кажется, в случае с array binding это неверно. Серверу достоверно известно, что нужно один и тот же sql-оператор выполнить над кучей параметров. Да еще как атомарное действие. С чего это он будет на каждый набор параметров перепарсивать запрос??? Очень сомнительно.
Как раз для Prepared будет создаваться массив параметров запроса, а не массив запросов.
S>Понятно что данные относительны для конкретного компа
А еще — для конкретного запроса, структур данных, статистики, настроек оптимизатора
Для вставки все проще.
S>, но тем не менее умножаем на 100 000 циклов и имеем конкретный ощутимый результат.
Еще раз. Говорим про array binding. Один запрос на вставку сразу 10000 строк.
То есть если надо вставить 100 000, то умножай на 10 и получай лишних 10 ms
Здравствуйте, Igor Trofimov, Вы писали:
S>>Понятно что данные относительны для конкретного компа
iT>А еще — для конкретного запроса, структур данных, статистики, настроек оптимизатора iT>Для вставки все проще.
S>>, но тем не менее умножаем на 100 000 циклов и имеем конкретный ощутимый результат.
iT>Еще раз. Говорим про array binding. Один запрос на вставку сразу 10000 строк. iT>То есть если надо вставить 100 000, то умножай на 10 и получай лишних 10 ms
Протестировал для вставки: 10 000 записей в 4-е поля (int, double, String, Time)
Statement — 40 646 ms
Statement.addBatch — 14 439 ms
PreparedStatement — 34 660 ms
PreparedStatement.addBatch — 9 189 ms
Здравствуйте, stenkil, Вы писали:
S>Здравствуйте, Igor Trofimov, Вы писали:
S>>>Понятно что данные относительны для конкретного компа
iT>>А еще — для конкретного запроса, структур данных, статистики, настроек оптимизатора iT>>Для вставки все проще.
S>>>, но тем не менее умножаем на 100 000 циклов и имеем конкретный ощутимый результат.
iT>>Еще раз. Говорим про array binding. Один запрос на вставку сразу 10000 строк. iT>>То есть если надо вставить 100 000, то умножай на 10 и получай лишних 10 ms
S>Протестировал для вставки: 10 000 записей в 4-е поля (int, double, String, Time) S> Statement — 40 646 ms S> Statement.addBatch — 14 439 ms S> PreparedStatement — 34 660 ms S> PreparedStatement.addBatch — 9 189 ms
S>addBatch c PreparedStatement предпочтительней
Огромное спасибо, очень полезная инфа.
Скажите, пожалуйста, какой использовали драйвер, базу данных и настройки соединения?
Здравствуйте, stenkil, Вы писали:
S>Здравствуйте, Igor Trofimov, Вы писали:
S>>>Понятно что данные относительны для конкретного компа
iT>>А еще — для конкретного запроса, структур данных, статистики, настроек оптимизатора iT>>Для вставки все проще.
S>>>, но тем не менее умножаем на 100 000 циклов и имеем конкретный ощутимый результат.
iT>>Еще раз. Говорим про array binding. Один запрос на вставку сразу 10000 строк. iT>>То есть если надо вставить 100 000, то умножай на 10 и получай лишних 10 ms
S>Протестировал для вставки: 10 000 записей в 4-е поля (int, double, String, Time) S> Statement — 40 646 ms S> Statement.addBatch — 14 439 ms S> PreparedStatement — 34 660 ms S> PreparedStatement.addBatch — 9 189 ms
S>addBatch c PreparedStatement предпочтительней
Быть может вы знаете ответ на такой вопрос — произошла ошибка на очередном инсерте, где настраивается дальнейшее поведение, инсертить ли остальные строки или откатит все или оставить только те что уже прошли? и можно ли вообще это настроить, как вывести в лог инсерт на котором произошла ошибка?
Здравствуйте, Sahivi, Вы писали: S>Быть может вы знаете ответ на такой вопрос — произошла ошибка на очередном инсерте, где настраивается дальнейшее поведение, инсертить ли остальные строки или откатит все или оставить только те что уже прошли? и можно ли вообще это настроить, как вывести в лог инсерт на котором произошла ошибка?
Не понял — в случай batch insert ошибка может случится только на всем пакете, но никак ни на отдельном инсерте. У вас точно batch? Вообще, ошибки в batch-операциях, согласно спецификации ЖДБЦ, возвращаются в виде массива целочисленных кодов-статусов в ответ на executeBatch(). А ошибка могла быть, как вариант, на достижении граничного объема транзакции.
Здравствуйте, ika, Вы писали:
ika>Здравствуйте, Sahivi, Вы писали: S>>Быть может вы знаете ответ на такой вопрос — произошла ошибка на очередном инсерте, где настраивается дальнейшее поведение, инсертить ли остальные строки или откатит все или оставить только те что уже прошли? и можно ли вообще это настроить, как вывести в лог инсерт на котором произошла ошибка? ika>Не понял — в случай batch insert ошибка может случится только на всем пакете, но никак ни на отдельном инсерте. У вас точно batch? Вообще, ошибки в batch-операциях, согласно спецификации ЖДБЦ, возвращаются в виде массива целочисленных кодов-статусов в ответ на executeBatch(). А ошибка могла быть, как вариант, на достижении граничного объема транзакции.
да точно Batch просто необходимо уметь отлавливть какой инсерт допустим не прошел, к примеру может же быть такое что пробывал инсертиться непрвильный тип данных или символ какой запрещенный или там какое то стояло ограничение на таблице и оракл выдал ошибку, как поступает батч в этом случе он все данные откатывает или же удачно занесенные инсерты остаются?
S>Протестировал для вставки: 10 000 записей в 4-е поля (int, double, String, Time) S> Statement — 40 646 ms S> Statement.addBatch — 14 439 ms S> PreparedStatement — 34 660 ms S> PreparedStatement.addBatch — 9 189 ms S>addBatch c PreparedStatement предпочтительней
14 секунд — это как-то очень много и 9 — тоже для вставки 10000 записей batch'ем... ИМХО.
И на prepare INSERT'а ушло 5 секунд??? На чем вы это пускали?
S>>Протестировал для вставки: 10 000 записей в 4-е поля (int, double, String, Time) S>> Statement — 40 646 ms S>> Statement.addBatch — 14 439 ms S>> PreparedStatement — 34 660 ms S>> PreparedStatement.addBatch — 9 189 ms S>>addBatch c PreparedStatement предпочтительней
iT>14 секунд — это как-то очень много и 9 — тоже для вставки 10000 записей batch'ем... ИМХО. iT>И на prepare INSERT'а ушло 5 секунд??? На чем вы это пускали?
iT>Можно увидеть код?
Celeron 2.4, RAM 248Mb, Win XP, FB Server: local host
Куда сбросить код?