Jag vet att andra har nämnt detta och du vill inte höra det utan använda SQL*Loader eller externa tabeller. Min genomsnittliga laddningstid för tabeller med ungefär samma bredd är 12,57 sekunder för drygt 10m rader. Dessa verktyg har uttryckligen utformats för att ladda data till databasen snabbt och är ganska bra på det. Detta kan medföra ytterligare tidsstraff beroende på formatet på din indatafil, men det finns en hel del alternativ och jag har sällan behövt ändra filer innan de laddas.
Om du inte är villig att göra detta behöver du inte uppgradera din hårdvara ännu; du måste ta bort alla möjliga hinder för att ladda detta snabbt. Ta bort:
för att räkna upp dem- Indexet
- Utlösaren
- Sekvensen
- Partitionen
Med alla dessa tvingar du databasen att utföra mer arbete och eftersom du gör detta transaktionsmässigt använder du inte databasen till dess fulla potential.
Ladda data till en separat tabell, säg ABC_LOAD
. Efter att data har laddats helt, utför en enkel INSERT-satsen i ABC.
insert into abc
select abc_seq.nextval, a.*
from abc_load a
När du gör detta (och även om du inte gör det) se till att storleken på sekvenscachen är korrekt; för att citera:
När ett program kommer åt en sekvens i sekvenscachen läses dessa sekvensnummer snabbt. Men om ett program får åtkomst till en sekvens som inte finns i cachen, måste sekvensen läsas från disken till cachen innan sekvensnumren används.
Om dina applikationer använder många sekvenser samtidigt, kanske din sekvenscache inte är tillräckligt stor för att hålla alla sekvenser. I det här fallet kan åtkomst till sekvensnummer ofta kräva diskläsning. För snabb åtkomst till alla sekvenser, se till att din cache har tillräckligt många poster för att hålla alla sekvenser som används samtidigt av dina applikationer.
Detta betyder att om du har 10 trådar som samtidigt skriver 500 poster var och en med den här sekvensen behöver du en cachestorlek på 5 000. ALTER SEQUENCE-dokumentet anger hur du ändrar detta:
alter sequence abc_seq cache 5000
Om du följer mitt förslag skulle jag öka cachestorleken till något runt 10,5 m.
Titta på hur du använder APPEND-tipset (se även Oracle Base); detta instruerar Oracle att använda en direktvägsinfogning, som lägger till data direkt i slutet av tabellen istället för att leta efter utrymme för att lägga det. Du kommer inte att kunna använda detta om din tabell har index men du kan använda den 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
Om du använder APPEND-tipset; Jag skulle lägga till TRUNCATE ABC_LOAD
efter att du har infogat i ABC
annars kommer denna tabell att växa på obestämd tid. Detta bör vara säkert eftersom du kommer att ha slutat använda tabellen då.
Du nämner inte vilken version eller utgåva eller Oracle du använder. Det finns ett antal extra små knep du kan använda:
-
Oracle 12c
Denna version stöder identitetskolumner; du kan bli av med sekvensen helt.
CREATE TABLE ABC( seq_no NUMBER GENERATED AS IDENTITY (increment by 5000)
-
Oracle 11g r2
Om du håller avtryckaren; du kan tilldela sekvensvärdet direkt.
:new.seq_no := ABC_seq.nextval;
-
Oracle Enterprise Edition
Om du använder Oracle Enterprise kan du snabba på INSERT från
ABC_LOAD
genom att använda PARALLELL-tipset:insert /*+ parallel */ into abc select abc_seq.nextval, a.* from abc_load a
Detta kan orsaka sina egna problem (för många parallella processer etc), så testa. Det kan hjälp för de mindre batch-inläggen men det är mindre troligt eftersom du förlorar tid på att beräkna vilken tråd som ska bearbeta vad.
tl;dr
Använd verktygen som följer med databasen.
Om du inte kan använda dem så gör du av med allt som kan bromsa insättningen och gör det i bulk, för det är vad databasen är bra på.