|
|
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Garrickalexei_kИ N там не особо большое (как-то типа 10), и повлиять на это N, насколько я помню, в JDBC API никак нельзя. За всех не скажу, но в Orcale есть setDefaultExecuteBatch , хоть оно и Deprecated, но все ещё работает. Deprecated и должно работать. Но вообще круто. :) Похоже в актуальной версии JDBC спеки они что-то подстелили под проблему. Надо было бы поковыряется... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 17:39 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
alexei_kКак именно работает Batch зависит от конкретного JDBC драйвера и от конкретного БД сервера. Базовая идея там прямолинейна как грабли - строим скрипт с кучей запросов и пуляем его одним пакетом на сервер. Понятно что если массив будет очень большим (мильён элементов, например) то результат будет совершенно печальным. обычно JDBC драйвера не такие тупые, они не отправляет весь скрипт одним запросом к базе а бьют на куски по N запросов в каждом. И N там не особо большое (как-то типа 10), и повлиять на это N, насколько я помню, в JDBC API никак нельзя. В итоге вы выполняете конечно на порядок, а то и на два меньше запросов к базе, сравнительно с "работой по одному" и это намного быстрей, но при больших объемах данных это все равно 100-и и 1000-и запросов и это все равно неприемлемо медленно. Возможно конечно ваша БД поддерживает какие то особые трюки для этого и ваш JDBC драйвер даже о них знает. Но.. Но, как правило когда речь идет о insert/update очень большого количества данных, то делать это приходится используя специальные средства сервера БД: прямой BULK INSERT из файла с данными и тому подобное. У меня в практике был такие истории. 10 миллионов строк bacth-eм - два часа. Слить данные файл -> FTP его на сервер -> BULK insert там из файла в temp-тамблицу -> update основной таблицы на основе temp -> стереть за собой весь мусор = полторы минуты на все. похоже вы его использовали не верно или железо дореволюционное было как на сервере, так на клиенте. 2,5 миллиона строк с 85-ю колонок разнотипных данных из файла в базу с разбором данных залетают за 2,5 минуты... Весит это барахло 2,2 Гб в текстовом виде. База оракловая. PreparedStatement, JDBC addBatch... Если честно (совсем откровенно) то распаковка такого файла (данные поступают в архивах), у меня больше времени занимает чем разбор и вставка в базу. Кстати на счет N, то похоже на бред, я конечно не знаю как на низком уровне пакеты делятся (на уровне общения сетевых устройств). Но на высоком - делить вы можете сами, я по 1000 делил например. Почему именно 1000, опытным путем получил оптимальное число под мою систему, которое не так сильно влияет на память и меня устраивает по производительности. Покажите ваш код, с момента где вы получили коннекшн (без автокоммита), создали ваш препаред, запихали туда данных и батч. Уверен тормоза где-то между ними. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 17:55 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Я когда свой загрузчик сделал, кол-во на батч вычислял как N МегаБайт под буфер / M размер одной записи. На больших размерах пакетов начинает тормозить система, маленькие не эффективны. Но у нас в основном таблицы-связки (N:N) заливались, там мало коротких полей и много записей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 18:03 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Ну значит Oracle и его JDBC драйвер умеют решать проблему по-умному. Респект Oracle-у, недаром столько стоит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 18:10 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Leonid KudryavtsevСлова direct load мне вообще не очень понятны. У меня чувство, что под этими словами практически скрывается __только__ hint APPEND. Но это уже лучше в доке почитать. Начну с середины. Буду каментить пока по тому где есть мысли. Про Direct Path Load пишут здесь. http://docs.oracle.com/cd/B28359_01/server.111/b28319/ldr_modes.htm#i1008815 Direct Path Load Instead of filling a bind array buffer and passing it to the Oracle database with a SQL INSERT statement, a direct path load uses the direct path API to pass the data to be loaded to the load engine in the server. The load engine builds a column array structure from the data passed to it. The direct path load engine uses the column array structure to format Oracle data blocks and build index keys. The newly formatted database blocks are written directly to the database (multiple blocks per I/O request using asynchronous writes if the host platform supports asynchronous I/O). Internally, multiple buffers are used for the formatted blocks. While one buffer is being filled, one or more buffers are being written if asynchronous I/O is available on the host platform. Overlapping computation with I/O increases load performance. Работает действительно быстро. Насчёт 10х кратного ускорения возможно я погорячился но в 2 и более раз будет. К сожалению есть ограничения. Direct Path ЕМНИП поддерживается для базовых типов данных таких как NUMBER/VARCHAR2/DATE. По поводу hint append. Мы проводили эксперимент на 10g и пришли к выводу что хинт +APPEND выгоден на массовых операциях где на один оператор INSERT фактически идёт вставка более чем 1-й строки (INSERT .... SELECT ...). В других случаях он не имеет полезного эффекта. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 20:40 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Вообщем, посмотрев на stackoverflow, здесь, пришел к выводу что лучше чем batch в джаве ничего быстрее нету(а может и правильно). Для PostgreSQL есть COPY (он кстати работает быстрее чем батч), но если переливать данные с одной базы в другую, как то не красиво экспортировать её в csv на клиент :) Возможно неплохо было бы иметь direct path возможность в execute(). PS append hint=direct path. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 23:29 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
alexei_kБазовая идея там прямолинейна как грабли - строим скрипт с кучей запросов и пуляем его одним пакетом на сервер. Понятно что если массив будет очень большим (мильён элементов, например) то результат будет совершенно печальным. Да. Я тоже думаю что эффект batch базируется на оптимизации сетевого взаимодействия. Только вот размер пачки будет зависеть от самих данных и его скорее всего надо подбирать экспериментально. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2016, 23:54 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
1. Oracle доке не всегда можно верить. Разбирался (на коммерческой основе) с Array fetch / batch операциями с Blob'ами на Java Thin JDBC - дока во многих местах противоречит друг другу и/или содержит заведомо устаревшие сведения. Ряд возможностей вообще были найдены только в секции new futures для JDBC. В самой доке описание флагов отсутствовало. 2. Это я читал, но когда плотно столкнулся в начале 2000-х (Oracle 8.1.5, MS VS C, OCI) это выглядело как "у нас есть супер оружие, но мы вам не покажем" ( C ) Ровно так Bulk insert и работает. Готовим буфер, выполняем Insert. Ограничения по типам - сейчас уже не уверен. Раньше Array fetch/bulk операции не поддерживали BLOB'ы, сейчас с 11-ых версий (сервер вроде с 10.1 /частично/-11.1, JDBC с 11.2/ BLOB'ы поддерживаются. 3. Разумеется, хинт APPEND имеет смысл только для _массовых_ операциях. Мы о них сейчас и говорим. Мало того, в ряде случаев он крайне ВРЕДЕН (при неумеренном использовании не по делу, может вызвать дикую фрагментацию таблицы и положить Oracle). БЫЛ НЕ ПРАВ. Почитал описание JDBC драйверов от MS, там таже уверяют, что просто выполняем кучу независимых команд и делаем Batch. Я так никогда не делал. Всегда делал PreparedStatement и уже операции с ним. Вообще всегда только через PreparedStatement работаю. 4. По документации Oracle JDBC содержит/содерЖАЛ паралельно 2-е технологии: Java JDBC array fetch/bulk, "native Oracle". Чем конкретно они различаются - в доке не написано и, вообще, опции относящиеся к этим обеим технологиям описаны очень куце и противоречиво (специально искал все связанное с BLOB). Выбор режима в ряде случаев просто параметром. Единственная осмысленная рекомендация в доках "не смешивайте и тот и тот вариант в одной программе" На практике, IMHO по скорости РАЗНИЦЫ НЕ ВИДНО (на моем коде, см. выше). Кроме того, методы "native Oracle" в каждой версии все больше и больше deprecated. Т.ч. есть подозрении, что внутри одно и то же. Возможно, для ранних драйверов (особенно, когда использовался OCI драйвер) - различия и были. Сейчас - сильно сомневаюсь. Если раньше OCI драйвер рекомендовался как "он быстрее", то сейчас сам Oracle Co. рекомендует всегда использовать Thin. В том числе, так как он стал быстрее OCI. IMHO & AFAIK ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 09:16 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
ora601..Для PostgreSQL есть COPY (он кстати работает быстрее чем батч), но если переливать данные с одной базы в другую, как то не красиво экспортировать её в csv на клиент Нафига что-то держать на клиенте? У Postgres JDBC есть классы, просто туда запихиваешь поток и пихаешь его в БД. Недостаток - типы данных нужно самому форматировать. Уже не помню, но на реальных данных местами у меня были заморочки с форматированием. На чем-то простом, типа Number'ов. В каких конкретно случаях. Изначально хотел делать binary формат, потом посмотрев загрузку на сервере, понял, что для меня выгоды binary / text особой не будет. Т.ч. даже заморачиваться не стал. IMHO & AFAIK У PostgreSQL COPY выглядит просто "bulk" вариантом команды INSERT. Если я правильно помню AFAIK, она даже меннее специфическая, чем Oracle хинт /*+ append*/ (у Oracle INSERT + append есть ограничения по использованию в пределах транзакций, у PostgreSQL COPY вроде никаких ограничений нет). Как я понимаю, просто не сделаны/реализованы нормальны PreparedStatement'ы, вот и пришлось костыль в виде COPY сооружать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 09:25 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
INSERT /*+ append */ с JDBC не смотрел, потребности не было. Т.ч. точно ничего сказать не могу. Нужно смотреть и проверять. Сейчас Oracle под рукой нет, да и интерес чисто академический. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 09:27 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Leonid Kudryavtsev... На практике, IMHO по скорости РАЗНИЦЫ НЕ ВИДНО (на моем коде, см. выше)... Беглым поиском в И-нет наткнулся на статью: https://venzi.wordpress.com/2007/11/28/prepared-statement-in-batch-mode-vs-forall-in-plsql/ Человек сравнил Insert через Java batch и хитровывернутый anonymous PL/SQL блок с честным PL/SQL BULK INSERT. Просто Insert через Java batch оказался быстрее. Никакие хитровывернутые пляски в современных драйверах нафиг не нужны. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 09:36 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Один из самых быстрых способов загрузки в Oracle из CSV в качестве примера я приводил здесь Тяпничная география ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 14:20 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
maytonПо поводу hint append. Мы проводили эксперимент на 10g и пришли к выводу что хинт +APPEND выгоден на массовых операциях где на один оператор INSERT фактически идёт вставка более чем 1-й строки (INSERT .... SELECT ...). В других случаях он не имеет полезного эффекта. Ну так в документации же написано было The APPEND hint is only supported with the subquery syntax of the INSERT statement, not the VALUES clause. Другим словами, чтоб заставить его работать можно, как было указано выше, сериализовать в джаве каждый объект в строку (если влезает в 4000 байт), передать в запрос через типизированный массив, ну например SYS.ODCIVARCHAR2LIST, и сделать insert ... select from table(...). Если строк много то сделать теми же порциями с переиспользованием preparedSatatement. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 15:24 |
|
||
|
Как правильно вставить ArrayList в SQL таблицу ?
|
|||
|---|---|---|---|
|
#18+
Беглым поиском находится еще хинт APPEND_VALUES (с 11g release 2). Но поскольку такое нужно достаточно редко - лично я в голове все эти подробности не держу. Помню, что нечто нужное есть, а все остальные подробности - RTFM. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.03.2016, 15:35 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=39188493&tid=2124285]: |
0ms |
get settings: |
5ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
151ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
40ms |
get tp. blocked users: |
1ms |
| others: | 219ms |
| total: | 440ms |

| 0 / 0 |
