SQL> DELETE FROM TEMPTABLE WHERE ID BETWEEN 1000000 AND 3000000; SQL> COMMIT;
a hotovo.
Áno, príkaz je platný a syntakticky správny. Problém ale nastane, keď množina riadkov, ktoré chceme vymazať z tabuľky obsahuje v blokoch (menšie jednotky, v ktorých ORACLE databázový server ukladá dáta na disk) rádove desiatky MB,
stovky MB alebo celé GB dát. Vtedy môže trvať spracovanie príkazu aj niekoľko hodín. Ukážeme si preto, ako efektívnejšie vymazať veľký počet riadkov z tabuľky. Príklad som testoval na databázovom prostredí Oracle 11g.
Príklad:
Chceme vymazať z tabuľky TEMPTABLE asi 2 milióny záznamov, ktoré môžu zaberať na disku dosť veľký priestor.
Najjednoduchšie je samozrejme napísať a spustiť už spomenutý príkaz hore:
DELETE FROM TEMPTABLE WHERE ID BETWEEN 1000000 AND 3000000;
Ak by sme spustili tento príkaz, netrúfam si napísať, ako dlho by mohol trvať na vašom počítači. Možno rádovo niekoľko hodín.
Zvolíme trochu iný postup.
Predpoklady:
Užívateľ musí mať nagrantované práva na vytváranie a mazanie tabuliek, práva na pridávanie dát do "tablespace", kde sa nachádza tabuľka, v ktorej vymažeme riadky.
Databáza je v archívnom móde (nie je podmienkou). Treba mať v tabuľkovom priestore, v ktorom sa tabuľka nachádza dosť voľného miesta na vytvorenie kópie aktuálnej tabuľky.
1. Najprv si vytvoríme kópiu aktuálnej tabuľky (ktorá bude prázdna) - _TEMPTABLE.
SQL> CREATE TABLE _TEMPTABLE TABLESPACE TEMPTABLESPACE NOLOGGING AS SELECT * FROM TEMP_TABLE WHERE 1=2;
Vytvoríme v tom istom tablespace prázdnu kópiu tabuľky _TEMPTABLE.
Na tabuľke je vypnuté logovanie, z dôvodu rýchlejšieho vkladania záznamov neskôr - NOLOGGING. Všetky DML príkazy na tabuľke, na ktorej je zapnuté logovanie sú logicky pomalšie.
Indexy a "constraints" nie sú na tabuľke vytvorené, vytvoriť ich treba až po celej akcii. Tento stav nám vyhovuje nateraz, lebo akýkoľvek "constraint" alebo index na tabuľke by nám takisto spomaľoval vkladanie riadkov a o to nám teraz práve ide.
2. Premiestnime do novej kópie tabuľky _TEMPTABLE tie dáta, ktoré nemajú byť vymazané.
SQL> INSERT /*+ APPEND PARALLEL(_TEMPTABLE, 2) */ INTO _TEMPTABLE (COLUMN1, COLUMN2, .....) SELECT /*+ PARALLEL(TEMPTABLE,4) */ COLUMN1, COLUMN2, ..... FROM TEMPTABLE WHERE ID<1000000 AND ID> 3000000 /* podmienka, ktorá vyberie riadky, ktoré nemajú byť vymazané */ SQL> COMMIT;
V prípade, ze je povolený paralelizmus na DML príkazoch, odporúčam ho v tomto prípade použiť pre zrýchlené vykonanie. V prípade, že paralelizmus na databáze povolený nie je, je možné ho samozrejme v príkaze vynechať.
3. Vymažeme pôvodnú tabuľku TEMPTABLE príkazom:
SQL> DROP TABLE TEMPTABLE /* PURGE */;
Ak použijeme klauzulu "PURGE", tak objekt s dátami nebude premiestnený do "RECYCLE BIN" (ak je to povolené) a bude okamžite uvoľnený priestor v danom tabuľkovom priestore.
4. Premenujeme novú tabuľku na jej pôvodný názov.
SQL> RENAME _TEMPTABLE TO TEMPTABLE;
Potom nesmieme zabudnúť samozrejme zapnúť "constraints" plus indexy, ak na pôvodnej tabuľke boli a ak bolo zapnuté logovanie na tabuľke, treba ho tiež samozrejme dodatočne potom zapnúť.
Keďže využívame stav s NOLOGGING (DML príkaz sa neloguje do redologov), nie je možné operáciu vrátiť späť. Je vhodné pred takouto akciou mať vytvorenú celkovú kópiu databázy alebo pôvodnú tabuľku nemazať a ponechať si ju do zálohy.
S pozdravom.