sql >> Database teknologi >  >> RDS >> Oracle

SQLcl til at overføre data fra Oracle til PostgreSQL eller YugabyteDB 🅾🐘🚀

Gamle DBA'er har historier om, at Oracle leverer en "SQL*Loader" uden nogen "SQL*Unloader", fordi Larry Ellison ikke ønskede, at hans kunder skulle flytte ud. Dette har ændret sig:der er en nem måde at eksportere til CSV med en simpel set sqlformat csv i SQLcl. Følg Jeff Smiths blog for at vide mere om det.

Her er et eksempel. Jeg ønskede at flytte nogle eksempeldata fra Oracle til YugabyteDB for at sammenligne størrelsen. Jeg har en altid gratis Automonous Database, som inkluderer SSB-eksempelskemaet. Der er en LINEORDER-tabel, som er et par hundrede GB. Jeg henter DDL med dbms_metadata . Den eneste ændring, jeg skulle foretage, var sub(" NUMBER,"," NUMERIC,") og jeg deaktiverede begrænsninger og kollationsklausuler.

Selvfølgelig er der professionelle værktøjer til at konvertere et Oracle-skema til PostgreSQL. Den gode gamle ora2pg, eller AWS SCT, som også er fantastisk til at vurdere niveauet af ændringer, der kræves af en migration. Men for noget hurtigt, jeg er god med awk 😉

Så er eksporten let med set sqlformat csv og de få indstillinger til kun at udlæse data som feedback off pagesize 0 long 999999999 verify off . Jeg sender alt det til awk som bygger \copy kommando, der tager disse CSV-linjer, som de er. Jeg kan godt lide at lave små trin og derefter bygge 10000 linjer COPY kommandoer med (NR-data)%10000 , data indstilles i begyndelsen af ​​COPY-kommandoen. Det ville være nemt at sende dem parallelt, men jeg har muligvis ikke brug for det, fordi YugabyteDB er multithreaded.

Her er scriptet, jeg bruger - jeg har min Autonomous Database-pung i TNS_ADMIN, SQLcl installeret i mit hjem (en Oracle free tier ARM, som jeg også kører mit YugabyteDB-laboratorium på).

{
TNS_ADMIN=/home/opc/wallet_oci_fra ~/sqlcl/bin/sql -s demo/",,P455w0rd,,"@o21c_tp @ /dev/stdin SSB LINEORDER <<SQL
set feedback off pagesize 0 long 999999999 verify off
whenever sqlerror exit failure
begin
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'SEGMENT_ATTRIBUTES', false);
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'STORAGE', false);
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'CONSTRAINTS', false);
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'REF_CONSTRAINTS', false);
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'SQLTERMINATOR', true);
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'COLLATION_CLAUSE', 'NEVER');
end;
/
set sqlformat default
select dbms_metadata.get_ddl('TABLE','&2','&1') from dual ;
set sqlformat csv
select * from "&1"."&2" ;
SQL
} | awk '
/^ *CREATE TABLE /{
 table=$0 ; sub(/^ *CREATE TABLE/,"",table)
 print "drop table if exists "table";"
 schema=table ; sub(/\"[.]\".*/,"\"",schema)
 print "create schema if not exists "schema";"
}
/^"/{
 data=NR-1
 print "\\copy "table" from stdin with csv header"
}
data<1{
 sub(" NUMBER,"," numeric,")
}
{print}
data>0 && (NR-data)%1000000==0{
 print "\\."
 print "\\copy "table" from stdin with csv"
}
END{
 print "\\."
}
'

Outputtet kan sendes direkte til psql 😎

Her er min skærm, når jeg starter indlæsningen:

Det er et laboratorium, det giver ikke mening at måle forløbet tid, men jeg kiggede på rows_inserted statistik for at bekræfte, at alt er distribueret til de 3 noder i min distribuerede SQL-database. Selv med en enkelt klientsession er belastningen fordelt på hele klyngen.

Dette fungerer på samme måde for PostgreSQL, fordi det er det samme API:YugabyteDB bruger PostgreSQL oven på det distribuerede lager.

Alle komponenter i denne test er gratis og nemme at bruge:

  • VM'en er på Oracle Cloud Free tier (ARM), Oracle-databasen er en gratis autonom database 👉 https://www.oracle.com/cloud/free/
  • PostgreSQL er open source og gratis 👉 https://www.postgresql.org
  • YugabyteDB er open source og gratis 👉 https://www.yugabyte.com

  1. Oracle-strengfunktioner (fuld liste)

  2. Sådan udskiftes en mellemliggende MySQL- eller MariaDB-master med en Binlog-server ved hjælp af MaxScale

  3. MySQL - hvordan man front pad postnummer med 0?

  4. mysqli_fetch_array() forventer, at parameter 1 er mysqli_result, boolean givet i