Oracle
 sql >> Base de données >  >> RDS >> Oracle

INSERT de 10 millions de requêtes en moins de 10 minutes dans Oracle ?

Je sais que d'autres l'ont mentionné et vous ne voulez pas l'entendre, mais utilisez SQL * Loader ou des tables externes. Mon temps de chargement moyen pour des tableaux d'environ la même largeur est de 12,57 secondes pour un peu plus de 10 m de rangées. Ces utilitaires ont été explicitement conçus pour charger rapidement des données dans la base de données et sont assez bons dans ce domaine. Cela peut entraîner des pénalités de temps supplémentaires en fonction du format de votre fichier d'entrée, mais il existe de nombreuses options et j'ai rarement eu à modifier les fichiers avant le chargement.

Si vous ne souhaitez pas le faire, vous n'avez pas encore besoin de mettre à niveau votre matériel; vous devez supprimer tous les obstacles possibles au chargement rapide. Pour les énumérer, supprimez :

  1. L'indice
  2. Le déclencheur
  3. La séquence
  4. La partition

Avec tout cela, vous obligez la base de données à effectuer plus de travail et, comme vous le faites de manière transactionnelle, vous n'utilisez pas la base de données à son plein potentiel.

Chargez les données dans une table séparée, dites ABC_LOAD . Une fois les données complètement chargées, effectuez une simple Instruction INSERT dans ABC.

insert into abc
select abc_seq.nextval, a.*
  from abc_load a

Lorsque vous faites cela (et même si vous ne le faites pas), assurez-vous que la taille du cache de séquence est correcte ; pour citer :

Lorsqu'une application accède à une séquence dans le cache de séquence, ces numéros de séquence sont lus rapidement. Cependant, si une application accède à une séquence qui n'est pas dans le cache, la séquence doit être lue du disque vers le cache avant que les numéros de séquence ne soient utilisés.

Si vos applications utilisent plusieurs séquences simultanément, votre cache de séquences peut ne pas être assez grand pour contenir toutes les séquences. Dans ce cas, l'accès aux numéros de séquence peut souvent nécessiter des lectures de disque. Pour un accès rapide à toutes les séquences, assurez-vous que votre cache contient suffisamment d'entrées pour contenir toutes les séquences utilisées simultanément par vos applications.

Cela signifie que si vous avez 10 threads écrivant simultanément 500 enregistrements chacun en utilisant cette séquence, vous avez besoin d'une taille de cache de 5 000. Le document ALTER SEQUENCE indique comment changer cela :

alter sequence abc_seq cache 5000

Si vous suivez ma suggestion, j'augmenterais la taille du cache à environ 10,5 m.

Envisagez d'utiliser l'indicateur APPEND (voir aussi Oracle Base); cela indique à Oracle d'utiliser une insertion de chemin direct, qui ajoute les données directement à la fin de la table plutôt que de chercher de l'espace pour les mettre. Vous ne pourrez pas l'utiliser si votre table a des index mais vous pouvez l'utiliser dans 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

Si vous utilisez l'indicateur APPEND ; J'ajouterais TRUNCATE ABC_LOAD après avoir inséré dans ABC sinon cette table grandira indéfiniment. Cela devrait être sûr car vous aurez fini d'utiliser la table d'ici là.

Vous ne mentionnez pas la version ou l'édition ou Oracle que vous utilisez. Il existe un certain nombre de petites astuces supplémentaires que vous pouvez utiliser :

  • Oracle 12c

    Cette version prend en charge les colonnes d'identité ; vous pourriez vous débarrasser complètement de la séquence.

    CREATE TABLE ABC(
       seq_no         NUMBER GENERATED AS IDENTITY (increment by 5000)
    
  • Oracle 11g r2

    Si vous maintenez la gâchette ; vous pouvez attribuer directement la valeur de la séquence.

    :new.seq_no := ABC_seq.nextval;
    
  • Oracle Enterprise Edition

    Si vous utilisez Oracle Enterprise, vous pouvez accélérer l'INSERT à partir de ABC_LOAD en utilisant l'astuce PARALLEL :

    insert /*+ parallel */ into abc
    select abc_seq.nextval, a.*
      from abc_load a
    

    Cela peut causer ses propres problèmes (trop de processus parallèles, etc.), alors testez. Il pourrait aide pour les insertions de lots plus petits, mais cela est moins probable car vous perdrez du temps à calculer quel thread doit traiter quoi.

tl;dr

Utilisez les utilitaires fournis avec la base de données.

Si vous ne pouvez pas les utiliser, débarrassez-vous de tout ce qui pourrait ralentir l'insertion et faites-le en masse, car c'est ce à quoi la base de données est bonne.