Jeg ved, at andre har nævnt dette, og du ønsker ikke at høre det, men brug SQL*Loader eller eksterne tabeller. Min gennemsnitlige indlæsningstid for tabeller med omtrent samme bredde er 12,57 sekunder for lidt over 10m rækker. Disse hjælpeprogrammer er eksplicit designet til at indlæse data i databasen hurtigt og er ret gode til det. Dette kan medføre nogle ekstra tidsstraffe afhængigt af formatet på din inputfil, men der er en del muligheder, og jeg har sjældent været nødt til at ændre filer før indlæsning.
Hvis du ikke er villig til at gøre dette, behøver du ikke opgradere din hardware endnu; du skal fjerne enhver mulig hindring for at indlæse dette hurtigt. For at opregne dem skal du fjerne:
- Indekset
- Udløseren
- Rækkefølgen
- Partitionen
Med alle disse tvinger du databasen til at udføre mere arbejde, og fordi du gør dette transaktionsmæssigt, bruger du ikke databasen til sit fulde potentiale.
Indlæs dataene i en separat tabel, sig ABC_LOAD
. Når dataene er blevet fuldstændig indlæst, skal du udføre en enkelt INSERT sætning i ABC.
insert into abc
select abc_seq.nextval, a.*
from abc_load a
Når du gør dette (og selvom du ikke gør det), skal du sikre dig, at sekvenscachens størrelse er korrekt; for at citere:
Når et program får adgang til en sekvens i sekvenscachen, læses disse sekvensnumre hurtigt. Men hvis et program får adgang til en sekvens, der ikke er i cachen, skal sekvensen læses fra disk til cachen, før sekvensnumrene bruges.
Hvis dine applikationer bruger mange sekvenser samtidigt, er din sekvenscache muligvis ikke stor nok til at indeholde alle sekvenserne. I dette tilfælde kan adgang til sekvensnumre ofte kræve disklæsning. For hurtig adgang til alle sekvenser skal du sørge for, at din cache har nok poster til at indeholde alle de sekvenser, der bruges samtidigt af dine applikationer.
Dette betyder, at hvis du har 10 tråde, der samtidig skriver 500 poster, hver ved hjælp af denne sekvens, har du brug for en cachestørrelse på 5.000. ALTER SEQUENCE-dokumentet angiver, hvordan dette ændres:
alter sequence abc_seq cache 5000
Hvis du følger mit forslag, vil jeg øge cachestørrelsen til noget omkring 10,5 m.
Se nærmere på at bruge APPEND-tip (se også Oracle Base); dette instruerer Oracle om at bruge en direkte-sti-indsættelse, som tilføjer data direkte til slutningen af tabellen i stedet for at lede efter plads til at sætte dem. Du vil ikke være i stand til at bruge dette, hvis din tabel har indekser, men du kan bruge det i ABC_LOAD
insert /*+ append */ into ABC (SSM_ID, invocation_id , calc_id, ... )
select 'c','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'a','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'b','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'c','g',NULL, 'test', 123 , 'N', 'asdf' from dual
Hvis du bruger APPEND tippet; Jeg ville tilføje TRUNCATE ABC_LOAD
efter du har indsat i ABC
ellers vil denne tabel vokse i det uendelige. Dette burde være sikkert, da du til den tid er færdig med at bruge tabellen.
Du nævner ikke, hvilken version eller udgave eller Oracle du bruger. Der er en række ekstra små tricks, du kan bruge:
-
Oracle 12c
Denne version understøtter identitetskolonner; du kunne slippe af med sekvensen helt.
CREATE TABLE ABC( seq_no NUMBER GENERATED AS IDENTITY (increment by 5000)
-
Oracle 11g r2
Hvis du holder aftrækkeren; du kan tildele sekvensværdien direkte.
:new.seq_no := ABC_seq.nextval;
-
Oracle Enterprise Edition
Hvis du bruger Oracle Enterprise, kan du fremskynde INSERT fra
ABC_LOAD
ved at bruge det PARALLELLE tip:insert /*+ parallel */ into abc select abc_seq.nextval, a.* from abc_load a
Dette kan forårsage sine egne problemer (for mange parallelle processer osv.), så test. Det måske hjælp til de mindre batch-indsatser, men det er mindre sandsynligt, da du vil miste tid på at beregne, hvilken tråd der skal behandle hvad.
tl;dr
Brug de hjælpeprogrammer, der følger med databasen.
Hvis du ikke kan bruge dem, skal du slippe af med alt, der kan gøre indsatsen langsommere og gøre det i bulk, for det er det, databasen er god til.