Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Можно ли вызвать sql*loader через jdbc ? / 24 сообщений из 24, страница 1 из 1
13.03.2017, 13:51
    #39418086
just_vladimir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Всегда считал, что Oracle DB впереди планеты всей, но столкнулся с одним нюансом работы через jdbc, который почему то без проблем решается в PostgreSQL и MySQL, но при этом никак не могу найти способ сделать тоже самое в Oracle.

В общем задача стандартная и распространенная, есть csv файл, который нужно максимально эффективно протолкнуть в БД.

У MySQL это делается через jdbc конструкцией "LOAD DATA LOCAL INFILE 'С:\Temp\MyLocalCsvFileLocation.csv' INTO TABLE", ничего дополнительно на сервер тащить не нужно.

У PostgreSQL это делается чуть сложнее, нужно за анврапить соединение, создать специфичный для драйвера PostgreSQL класс CopyManager и проделать тоже самое:
Код: java
1.
2.
3.
PGConnection pgConnection = connection.unwrap(PGConnection.class);
CopyManager cpManager = pgConnection.getCopyAPI();
cpManager.copyIn("COPY  public.\"MY_SUPER_TABLE\" FROM STDIN WITH CSV", new FileReader(csvFile));


и точно так же ничего кроме jar'ника с драйвером не нужно.

А вот у Oracle какая то беда, нужно вызывать внешнюю тулзу (sql*loader), которой нужен OCI клиент и т.д., как то некрасиво... Или может быть я не прав и можно точно так же, обойтись thin драйвером, состоящим из одного jar'ника?
...
Рейтинг: 0 / 0
13.03.2017, 23:13
    #39418511
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
just_vladimir, если кратко - то нельзя.

jdbc использует упрощенный протокол (без Direct Path Load).

А sqlloader знает интерфейс OCI (нативный, не-JDBC). Грязный хак под названием
Direct-Path-Load позволяет загружать сведения из *.csv файлов не по 1 строке
а сразу целыми блоками прямо в datafiles. При этом мы кое-что теряем в удобстве. Не можем
делать промежуточные commits и вставлять посторонние транзакции в другие
таблицы. И есть еще нюасны с аллокацией экстентов.

Поэтому на стороне java вы можете либо вызвать ProcessBuilder и передать
ему "sqlldr ....." или можно поискать массу утилит загрузчиков из csv
на java.

Кажется у liquibase есть такая опция. Почитайте.
...
Рейтинг: 0 / 0
14.03.2017, 10:46
    #39418642
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
just_vladimirВ общем задача стандартная и распространенная, есть csv файл, который нужно максимально эффективно протолкнуть в БД.
вы работаете с веб проектами. Это гетерогенная среда, облака и ГУГЛ сервисы с распознаваниме речи и команд.
Не надо "толкать" )) через драйвер. Используйте передачу файфла через многочисленные сервисы.
ЗЫ
Уже HTTP протокол ломают, а вы всё по старинке.
...
Рейтинг: 0 / 0
14.03.2017, 13:32
    #39418853
just_vladimir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
maytonПоэтому на стороне java вы можете либо вызвать ProcessBuilder и передать
ему "sqlldr ....."
Это то, чего бы очень хотелось избежать ... Просто удивляет, почему в MySQL и PostgreSQL соответствующий API предусмотрен в рамках jdbc драйвера, а в Oracle он запрятан во внешнюю утилиту...
...
Рейтинг: 0 / 0
14.03.2017, 15:18
    #39419004
Vladimir Baskakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
а что, один раз распарсить инсёрт с забинденными переменными, а дальще читать CSV построчно, резать на поля и скармливать инсерту - это неинтересно? все равно же надо прописывать мэппинг полей файла на поля таблицы. ну так на несколько строк больше писать?

....... но не ужасужасужас
...
Рейтинг: 0 / 0
14.03.2017, 15:31
    #39419012
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
just_vladimirЭто то, чего бы очень хотелось избежать ... Просто удивляет, почему в MySQL и PostgreSQL соответствующий API предусмотрен в рамках jdbc драйвера, а в Oracle он запрятан во внешнюю утилиту...

Вообще-то, JDBC это стандарт.
Хотелось бы увидеть ссылку на ту страницу __стандарта__ где это описано.
...
Рейтинг: 0 / 0
14.03.2017, 15:40
    #39419014
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Вопрос в Java форуме почему в Oracle так, а не эдак? Ну, не написали они CSV импорт в рамках PL/SQL. Никто не мешает создать хранимку под собственные нужды. Либо вообще запускайте командную строку средствами Оракла. Решений масса.
...
Рейтинг: 0 / 0
14.03.2017, 16:32
    #39419084
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
На самом деле все там написали. Просто нужна правильная постановка задачи.
Что вы хотите делать? Грузить файлы? ОК. Как часто? Какого размера?
Как много средств вы готовы потратить на создание конфигурации?

Забегая вперед я могу сказать что Oracle позволяет вообще не грузить
данные а просто "примонтировать" csv файл как external table
и уделать по скорости и МайСКЛ и ПостргреС.

Это будет решением? Или это вас не устроит? А если не устроит - то
смотрите то что я выше написал.
...
Рейтинг: 0 / 0
14.03.2017, 16:49
    #39419099
Denis Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
On 14.03.2017 13:32, just_vladimir wrote:

> Это то, чего бы очень хотелось избежать ... Просто удивляет, почему в MySQL и PostgreSQL соответствующий API
> предусмотрен в рамках jdbc драйвера, а в Oracle он запрятан во внешнюю утилиту...

Есть же драйвера для чтения CSV, например: http://csvjdbc.sourceforge.net. Можно через него прочитать файл и через
оракловый драйвер вставить данные в таблицу.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
14.03.2017, 17:24
    #39419137
just_vladimir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
BlazkowiczВопрос в Java форуме почему в Oracle так, а не эдак? Ну, не написали они CSV импорт в рамках PL/SQL. Никто не мешает создать хранимку под собственные нужды. Либо вообще запускайте командную строку средствами Оракла. Решений масса.
А на вопрос в Oracle форуме был бы ответ, почему в вашем Java'овском драйвере ...
...
Рейтинг: 0 / 0
14.03.2017, 17:25
    #39419139
just_vladimir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Denis PopovЕсть же драйвера для чтения CSV, например: http://csvjdbc.sourceforge.net. Можно через него прочитать файл и через оракловый драйвер вставить данные в таблицу.
Где вы вообще такие решения находите ... Уж если и читать CSV, то через Apache Commons CSV
...
Рейтинг: 0 / 0
14.03.2017, 17:28
    #39419143
just_vladimir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Leonid Kudryavtsevjust_vladimirЭто то, чего бы очень хотелось избежать ... Просто удивляет, почему в MySQL и PostgreSQL соответствующий API предусмотрен в рамках jdbc драйвера, а в Oracle он запрятан во внешнюю утилиту...

Вообще-то, JDBC это стандарт.
Хотелось бы увидеть ссылку на ту страницу __стандарта__ где это описано.
Подождите, подождите, я где то написал, что такое описано в стандарте jdbc? Можно процитировать? Я писал о том, что разработчики MySQL и PostgreSQL позаботились пропилить нужную дырочку через jdbc драйвер, в которую можно слить файл для загрузки и это реально удобно, а вот в Oracle посчитали, что не надобно так делать.
...
Рейтинг: 0 / 0
14.03.2017, 17:33
    #39419147
just_vladimir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
maytonНа самом деле все там написали. Просто нужна правильная постановка задачи.
Что вы хотите делать? Грузить файлы? ОК. Как часто? Какого размера?
Как много средств вы готовы потратить на создание конфигурации?

Забегая вперед я могу сказать что Oracle позволяет вообще не грузить
данные а просто "примонтировать" csv файл как external table
и уделать по скорости и МайСКЛ и ПостргреС.

Это будет решением? Или это вас не устроит? А если не устроит - то
смотрите то что я выше написал.
external table - файло должно жить на том же самом сервере, что и сам Oracle, не вариант. Хочу обратить внимание, что нет проблемы стандартными средствами эффективно загрузить файл (прочитать Apache Commons CSV, потом вставить через addBatch/executeBatch, выполняя insert с хинтом /* +append */), есть проблема, что есть специально созданный для этих целей функционал и нет возможности им воспользоваться через jdbc.
...
Рейтинг: 0 / 0
14.03.2017, 18:37
    #39419213
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
just_vladimirэффективно загрузить файл (прочитать Apache Commons CSV, потом вставить через addBatch/executeBatch, выполняя insert с хинтом /* +append */)
Ты вообще понимешь как работает хинт "+append" ?
...
Рейтинг: 0 / 0
14.03.2017, 19:02
    #39419234
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
maytonjust_vladimirэффективно загрузить файл (прочитать Apache Commons CSV, потом вставить через addBatch/executeBatch, выполняя insert с хинтом /* +append */)
Ты вообще понимешь как работает хинт "+append" ?

А что не так ?

Если верить I-net'у addBatch / executeBatch в Oracle JDBC порождают нормальный Bulk insert вызов SQL. Т.ч. весь пакет будет выполнен одной командой, соответственно append (если я правильно понимаю) уменьшит нагрузку на Redo и аллокацию. Если I-net не врет. Лично я бы доки Oracle перечитал.

Другое дело, что кроме плюсов, append и минусы имеет. Огромные. Использованием append очень легко всю систему убить (наблюдал такое на реальной задаче в ERP системе)

just_vladimirПодождите, подождите....

Тогда зачем вообще упоминать JDBC всуе )))

just_vladimirВ общем задача стандартная и распространенная, есть csv файл, который нужно максимально эффективно протолкнуть в БД.

Ну Oracle дает 100500 способов это сделать. Зачем для решения этой задачи вообще Java ?

Я могу назвать 100500 причин почему это делать не нужно. Но лучше это обсуждать за пивом, а не на Инет форуме.

just_vladimirВ общем задача стандартная и распространенная...

Ровно так же, как стандартная и распространеная задача - форматирования диска. А PostgreSQL и MySQL полный отстой, т.к. такой команды в JDBC не сделали )))
...
Рейтинг: 0 / 0
14.03.2017, 19:11
    #39419241
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Leonid Kudryavtsevmaytonпропущено...

Ты вообще понимешь как работает хинт "+append" ?

А что не так ?

Если верить I-net'у addBatch / executeBatch в Oracle JDBC порождают нормальный Bulk insert вызов SQL. Т.ч. весь пакет будет выполнен одной командой, соответственно append (если я правильно понимаю) уменьшит нагрузку на Redo и аллокацию. Если I-net не врет. Лично я бы доки Oracle перечитал.

Другое дело, что кроме плюсов, append и минусы имеет. Огромные. Использованием append очень легко всю систему убить (наблюдал такое на реальной задаче в ERP системе)
В твоей постановке хинт append будет бесполезен.
...
Рейтинг: 0 / 0
14.03.2017, 20:34
    #39419306
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
maytonВ твоей постановке хинт append будет бесполезен.
Почему? В какой постановке и что значит полезен?

Direct patch load, из плюсов, как минимум должно redo log уменьшится. Ну и минусов в реальной жизни полно. Т.ч. я бы не злоупотреблял.

p.s. вроде не offtopic, напрямую с вопросом автора связано.
...
Рейтинг: 0 / 0
14.03.2017, 21:03
    #39419320
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
AFAIK

Я бы сформулировал проблему в двух пунктах:

1) Приведет ли addBatch / executeBatch в Oracle JDBC к полноценному Array / bulk insert'у.
Т.е. к передаче по сети и вставки всего пакета данных ОДНОЙ командой.

Вроде да.
http://oracle-internals.blogspot.ru/2012/09/plsql-bulk-insert-jdbc-batchexecute.html

2) Приведет ли использование хинта append в команде insert к direct path load'у ?

В Inet-е встречается утверждение, что direct path только для конструкции INSERT from SELECT.

Посмотрел доку, в http://docs.oracle.com/cd/B10501_01/server.920/a96540/statements_913a.htm#2063932 про это ни слово /но полно других ограничений/.

В подфоруму Oracle утверждается, что есть некая терминологическая путаница. Bulk insert как обозначение для конкретной конструкции PL/SQL - при которой direct path НЕ работает. И bulk insert просто применительно к методу вставки многих данных за раз в SQL.

Т.е. "bulk insert PL/SQL" директом не бывает, нужен INSERT from SELECT

Но в SQL, просто INSERT /*+append*/ VALUES () вполне себе работает. Иначе как direct path load с клиента запускать?
...
Рейтинг: 0 / 0
14.03.2017, 21:29
    #39419330
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Тема интересная. Но очень боянисто. В sql.ru/Oracle скорее всего уже обсуждалось.

Автору мы ответ уже дали. Если он хочет быстро загрузить - то задействует нужные
утилиты (в скобках замечу что точно также как и в PGSQL, MySQL). Если он (автор) просто
капризничает или хочет птичьего молока - то пусть обосновывает
почему на Java, почему скорости недостаточно и пусть приводит характеристики
ETL-процесса. Сколько строк надо загрузить. Как часто e.t.c.

Иначе разговор получается философский.
...
Рейтинг: 0 / 0
14.03.2017, 22:23
    #39419348
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
повторюсь

maytonТема интересная. Но очень боянисто. В sql.ru/Oracle скорее всего уже обсуждалось.

В последние несколько лет периодически всплывает. При этом в "баянистом" виде (((

Но с другой стороны, тема важная /интеграция, обмен данных, performance/, нужная и наверное не простая /раз всплывает/

maytonв скобках замечу что точно также как и в PGSQL, MySQL

Не совсем. CSV к SQL никакого отношения не имеет, поэтому в Oracle решается внешними утилитами. В Postgres это зачем-то реализовано на уровне ядра СУБД.

Если кто считает по другому - просьба ссылку на стандарт ANSI SQL описывающий команды работы с CSV

1)
Oracle JDBC нормально поддерживает array / bulk операции при insert. В том числе, поддерживает direct path load. Хотя в одной из прошлых тем, термин direct path load от Oracle участниками трактовался не однозначно.

Что, и теоретически, и практически, позволяет на СТАНДАРТНОМ JDBC обеспечить функциональность и производительно близкую к специальным инструментам (sqlloader)

http://www.sql.ru/forum/1245207/java-i-api-directpath-oracle

2)
Postgre SQL array / bulk операции на вставку поддерживает через одно место. Максимум, может сцепить все команды в одну строчку. (вроде как и MySQL).

Поэтому, для массовой вставки команда INSERT в PgSQL не годится как класс. Приходится использовать команду COPY, которая, командой SQL (в нормальном смысле этого слова) НЕ ЯВЛЯЕТСЯ.

И специально для команды COPY изобретать "велосипед" как ей скармливать данные.

Замечу, что при этом, создав сей велосипед, авторы не удосужились написать форматеры/парсеры для типов данных поддерживаемых PgSQL. И, даже, не описали форматы. В документации PgSQL для команды COPY в binary режиме просто написано - возьмите исходный код на C и посмотрите в нашем исходном коде )))

В общем, из за убожества PgSQL изобретен "велосипед":

a) Команда COPY реализована на уровне ядра СУБД. Что, понятно, ни в каких стандартах SQL нет и любому стандарту SQL противоречит
b) В драйверах сделан велосипед, позволяющий использовать велосипед из СУБД. Что, опять таки, никакого отношения к JDBC не имеет.

В общем, от криворукости сотворили [мат вырезан] "дырочку" которая никаким образом к "задача стандартная и распространенная" не относится.

Еще одна такая криворукость PgSQL - тип text / binary. То есть, она тоже может показаться удобной "дырочкой" ))) например не имеет ограничения 4000 как varchar2 в Oracle. Пока, в этой дырочке, что нибудь не застрянет (((

Note: жизненная мудрость. Есть что нибудь в дырочку не впихивается, это пол беды, всегда есть вазелин. А вот если там что нибудь застревает - это уже серьезно. Т.ч. перед тем как запихивать что нибудь сложно впихуемое, лучше подумать.
...
Рейтинг: 0 / 0
15.03.2017, 10:51
    #39419582
Vladimir Baskakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Коллеги, а как Вы пакетами вставляли?

Я то на перле по простому делал - размножал текст инсерта, с забинденными переменными,
вставлял от между бегином - эндом, парсил а дальше - связывал последовательно и экзекьютил раз за разом.

Ну на джаве бы все один в один бы повторил, а как еще можно?

Код: perl
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
use DBD::Oracle qw(:ora_types);

use DBI;  
$dbname_from=
$user_from=;
$passwd_from=;


$dbname_to=;
$user_to=;
$passwd_to=;






$dbh_from = DBI->connect("dbi:Oracle:$dbname_from", $user_from, $passwd_from);   

$dbh_to = DBI->connect("dbi:Oracle:$dbname_to", $user_to, $passwd_to,{PrintError=>1,AutoCommit=>0,RaiseError=>1}) ;  





sub pack_sql{
  my ($sql,$cnt)=@_;
  
  my $res="begin \n";
  
  for ($i=0; $i<$cnt; $i++) {
    $res=$res . $sql . ";\n" 
  }
  $res=$res . "commit; \n end;";
  return $res;
}

sub process{
  our $dbh_from, $dbh_to;

  my ($sql_query,$sql_insert,$sql_delete,$fn)=@_;
  my $sth_from=$dbh_from->prepare($sql_query);
  $sth_from->execute();

  my $f, $sth_to;
  
  $sth_to=$dbh_to->prepare($sql_delete);
  $sth_to->execute();

  my $pack_size=100;
  
  # один оператор вставки превращаем в пакет
  $sth_to=$dbh_to->prepare(pack_sql($sql_insert,$pack_size));

  my $v,$cr;

  #open $f, ">$fn";
  $cr=0;
  @pack=();
  $n_pack=0;
  

  while( my @res_str = ($sth_from->fetchrow_array()) ) {
    # все поля источника пропихиваем в связ.переменные запроса вставки
    #print join(',',@res_str) . "\n";
    #print @res_str . "\n";
    push @pack, @res_str;
    $n_pack++;
    if ($pack_size==$n_pack) {
       $n=1;
       foreach $v (@pack) {
         $sth_to->bind_param($n++,$v);     
       }
       
       $sth_to->execute();
       @pack=();
       $n_pack=0;
    }
  }
  if ($n_pack) {
    $sth_to=$dbh_to->prepare(pack_sql($sql_insert,$n_pack));
       $n=1;
       foreach $v (@pack) {
         $sth_to->bind_param($n++,$v);     
       }
       $sth_to->execute();
  }
  $dbh_to->commit(); 
  print "$sql_query \nDONE!\n\n";
}



$sql_acc=qq{
select * from 
};

process($sql_acc,
"insert into ....  values (?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?)",
"delete from ",
".....rez"
);



$dbh_from->disconnect();
$dbh_to->disconnect();

...
Рейтинг: 0 / 0
15.03.2017, 11:00
    #39419604
Garrick
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
...
Рейтинг: 0 / 0
15.03.2017, 11:13
    #39419624
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Vladimir Baskakovсвязывал последовательно и экзекьютил раз за разом.

Экзекьютить можно целиком пакет. В оптимале, весь пакет данных из многих строк БД пойдет на сервер одним сетевым round trip'ом.

Первая ссылка из google (внимательно читать комментарии под статьей!):

http://betteratoracle.com/notes/25-array-batch-inserts-with-jdbc
...
Рейтинг: 0 / 0
16.03.2017, 11:11
    #39420584
Vladimir Baskakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли вызвать sql*loader через jdbc ?
Коллеги, спасибо!
Весьма интересно!
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Можно ли вызвать sql*loader через jdbc ? / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]