Vím, že to ostatní zmínili a nechcete to slyšet, ale použijte SQL*Loader nebo externí tabulky. Moje průměrná doba načítání pro tabulky přibližně stejné šířky je 12,57 sekund pro řádky něco přes 10 m. Tyto nástroje byly výslovně navrženy tak, aby rychle načítaly data do databáze a jsou v tom docela dobré. To může způsobit další časové sankce v závislosti na formátu vašeho vstupního souboru, ale existuje několik možností a jen zřídka jsem musel soubory před načtením měnit.
Pokud to nejste ochotni udělat, nemusíte svůj hardware ještě upgradovat; musíte rychle odstranit všechny možné překážky načítání. Chcete-li je vyjmenovat, odstraňte:
- Index
- Spouštěč
- Posloupnost
- Oddíl
Tím vším zavazujete databázi, aby vykonala více práce, a protože to děláte transakčně, nevyužíváte databázi naplno.
Načtěte data do samostatné tabulky, řekněte ABC_LOAD
. Po úplném načtení dat proveďte jednou Příkaz INSERT do ABC.
insert into abc
select abc_seq.nextval, a.*
from abc_load a
Když to uděláte (a i když to neuděláte), ujistěte se, že velikost mezipaměti sekvence je správná; abych citoval:
Když aplikace přistupuje k sekvenci v mezipaměti sekvencí, sekvenční čísla jsou načtena rychle. Pokud však aplikace přistupuje k sekvenci, která není v mezipaměti, musí být sekvence načtena z disku do mezipaměti, než se použijí sekvenční čísla.
Pokud vaše aplikace používají mnoho sekvencí současně, pak vaše mezipaměť sekvencí nemusí být dostatečně velká, aby pojala všechny sekvence. V tomto případě může přístup k sekvenčním číslům často vyžadovat čtení z disku. Pro rychlý přístup ke všem sekvencím se ujistěte, že vaše mezipaměť má dostatek záznamů pro uložení všech sekvencí používaných současně vašimi aplikacemi.
To znamená, že pokud máte 10 vláken současně zapisujících 500 záznamů pomocí této sekvence, pak potřebujete velikost mezipaměti 5 000. Dokument ALTER SEQUENCE uvádí, jak to změnit:
alter sequence abc_seq cache 5000
Pokud se budete řídit mým návrhem, zvýšil bych velikost mezipaměti na něco kolem 10,5 m.
Podívejte se na použití nápovědy APPEND (viz také Oracle Base); tím Oracle instruuje, aby použil vložení přímé cesty, které připojí data přímo na konec tabulky, místo aby hledal místo pro jejich umístění. Toto nebudete moci použít, pokud má vaše tabulka indexy, ale můžete to použít v 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
Pokud použijete nápovědu APPEND; Přidal bych TRUNCATE ABC_LOAD
po vložení do ABC
jinak tato tabulka poroste donekonečna. To by mělo být bezpečné, protože do té doby tabulku dokončíte.
Neuvádíte, jakou verzi nebo edici nebo Oracle používáte. Existuje řada dalších malých triků, které můžete použít:
-
Oracle 12c
Tato verze podporuje sloupce identity; můžete se sekvence úplně zbavit.
CREATE TABLE ABC( seq_no NUMBER GENERATED AS IDENTITY (increment by 5000)
-
Oracle 11g r2
Pokud necháte spoušť; hodnotu sekvence můžete přiřadit přímo.
:new.seq_no := ABC_seq.nextval;
-
Oracle Enterprise Edition
Pokud používáte Oracle Enterprise, můžete urychlit INSERT z
ABC_LOAD
pomocí PARALELNÍ nápovědy:insert /*+ parallel */ into abc select abc_seq.nextval, a.* from abc_load a
To může způsobit jeho vlastní problémy (příliš mnoho paralelních procesů atd.), takže testujte. Mohlo by pomoc pro menší dávkové vložky, ale je to méně pravděpodobné, protože ztratíte čas počítáním, které vlákno by mělo co zpracovat.
tl;dr
Použijte nástroje dodávané s databází.
Pokud je nemůžete použít, zbavte se všeho, co by mohlo vkládání zpomalit, a udělejte to hromadně, protože v tom je databáze dobrá.