Для следующего моделирования мы {A} сгенерировали таблицу STUDENT, содержащую 1 000 000 строк, заполненных случайными строками.Поскольку вы не сообщили нам , куда вы загружаете данные, мы {B} экспортировали / выгружали данные в файл CSV, а {C} использовали данные через таблицу EXTERNAL, которую мы затемиспользовать для различных методов вставки.(все сделано с помощью Oracle 12c, VM Developer Days)
{A} «Исходная таблица»
create table student ( name, address, phone, sclass )
as
select
dbms_random.string( 'x', 25 )
, dbms_random.string( 'x', 40 )
, dbms_random.string( 'x', 20 )
, dbms_random.string( 'x', 5 )
from dual
connect by level <= 1000000 ;
-- Elapsed: 00:03:25.032
-- quick check
select count(*) from student ;
COUNT(*)
----------
1000000
{B} записывает 1 000 000 строк в файл CSV
set term off
set feed off
set sqlformat csv
spool /home/oracle/data_out/out.csv
select /*+ parallel */* from student ;
spool off
{C} внешняя таблица
create table external_ (
name varchar2( 4000 )
, address varchar2( 4000 )
, phone varchar2( 4000 )
, sclass varchar2( 4000 )
)
organization external (
type oracle_loader
default directory external_tables
access parameters
(
records field names all files
fields CSV with embedded record terminators
)
location
(
'out.csv'
)
)
/
-- quick check
SQL> select count(*) from external_ ;
COUNT(*)
----------
1000000
таблица «назначения»
create table scholarship (
name varchar2( 25 )
, address varchar2( 40 )
, phone varchar2( 20 )
, sclass varchar2( 5 )
, sdate date default sysdate
);
При вставке 1 000 000 строк с использованием чистого SQL мы получили следующее время (тестовый запуск 3 разатаблица SCHOLARSHIP была сброшена между тестами.
-- {1} SQL: INSERT ... SELECT ...
insert into scholarship ( name, address, phone, sclass )
select name, address, phone, sclass from external_ ;
-- 1,000,000 rows inserted.
-- Elapsed: 00:00:02.607
-- Elapsed: 00:00:02.300
-- Elapsed: 00:00:02.473
Вероятно, худший вариант такой: использование PL / SQL и CURSOR FOR LOOP (тестовый прогон 3 раза, SCHOLARSHIP сбрасывается между тестами).
--{2} PL/SQL: use a cursor for loop ("slow by slow")
begin
for rec_ in ( select * from external_ )
loop
insert into scholarship ( name, address, phone, sclass )
values ( rec_.name, rec_.address, rec_.phone, rec_.sclass ) ;
end loop ;
commit ;
end ;
/
-- PL/SQL procedure successfully completed.
-- Elapsed: 00:00:24.777
-- Elapsed: 00:00:22.700
-- Elapsed: 00:00:24.291
Немного лучше: использовать массовые операции PL / SQL (снова с «истекшим временем» для 3 тестовых прогонов).
--{3} PL/SQL: use BULK COLLECT and FORALL (no need to re-compile in between tests)
create or replace procedure insert_students is
type student_t is table of external_%rowtype index by pls_integer ;
lstudents student_t ;
begin
select * bulk collect into lstudents from external_ ;
forall i in 1.. lstudents.count
insert into scholarship ( name, address, phone, sclass )
values ( lstudents( i ).name, lstudents( i ).address, lstudents( i ).phone, lstudents( i ).sclass );
end ;
/
begin
insert_students ;
commit ;
end ;
/
-- PL/SQL procedure successfully completed.
-- Elapsed: 00:00:08.706
-- Elapsed: 00:00:06.762
-- Elapsed: 00:00:04.989
Как вам скажут многие: используйте SQL (только) когда это возможно.Теперь вы, вероятно, видите, что ваш первоначальный подход - использование процедуры с параметрами и выполнение только одной вставки за раз - может быть не лучшим методом для решения вашей проблемы.