Oracle 11g: amélioration des performances des insertions


8

J'ai une table de 500 millions de lignes (et en croissance)

J'ai fait ce qui suit pour améliorer les performances des inserts:

Côté base de données:

  • abandonné tous les index et contraintes
  • journalisation désactivée

Côté application:

  • passage d'entités gérées JPA à des requêtes d'insertion natives, ajout d'un indice Oracle APPEND à la requête
  • essayé de valider par lots par 1k / 2k / 3k de lignes
  • essayé d'écrire en parallèle (plusieurs threads, nombre de threads = nombre de core sur le serveur) sur une table

Cela m'a donné environ 300 lignes par seconde

En outre essayé:

  • écrire en parallèle par lots sur plusieurs tables (pour regrouper puis sauvegarder les résultats en utilisant UNION)

Cela m'a donné environ 1 000 lignes par seconde, mais sur des tables vides. Mais lorsque j'ai rempli des tableaux avec des données factices (200 millions chacune), la vitesse des insertions est tombée à 250 - 300 par seconde.

Quelqu'un pourrait-il suggérer quoi d'autre pour accélérer les insertions? Fondamentalement, je veux d'abord comprendre quel est (ce qui pourrait être) le goulot d'étranglement.

UPD: la table est partitionnée par date d'insertion, la table a environ 60 colonnes - la plupart des colonnes sont VARCHAR2 (2000 BYTE)


Vous savez qu'avec la journalisation désactivée, une défaillance de support entre le chargement et la fin de la première sauvegarde subséquente laissera la table entière, ou des sections de celle-ci dans le cas d'une insertion de chemin direct, irrécupérable, non?
David Aldridge

1
(1) Une seule session peut AJOUTER à la fois sur une table. (2) l' /*+APPEND*/indication est ignorée sur les insertions à une seule ligne (si vous INSERT INTO ... SELECTn'avez pas la peine d'ajouter). (3) Vous devez configurer un exemple SQL * Loader avec direct=truepour établir une ligne de base comme suggéré par @parsifal.
Vincent Malgrat

Utilisez-vous du vrai matériel ou une machine virtuelle? S'il s'agit d'une machine virtuelle, les fichiers disque sont-ils rares (c'est-à-dire: pas entièrement préalloués)? En outre, veuillez modifier votre question avec la sortie d'un statspack ou d'un rapport awr (section des attentes supérieures).
Philᵀᴹ

Quel problème / besoin le partitionnement par date d'insertion résout-il / satisfait-il?
Brian

Quelle est la source de vos données pour ce tableau? S'agit-il d'un chargement par lots à partir d'un fichier ASCII ou est-il généré par l'utilisateur ou autre chose. Soyez précis s'il vous plait.
RMAN Express

Réponses:


5

Je viens de voir la mise à jour, la table 60-col avec principalement des champs VARCHAR (2k) - c'est (potentiellement) une table monstre.

Tout d'abord ...

Vous devez d'abord comprendre votre goulot d'étranglement. Du côté de l'application, retournez à votre solution d'insertion par lots à un seul thread (1/2 / 3k à la fois) et commencez à l'exécuter et connectez-vous à la machine DB et exécutez un `` top '' - voyez combien le temps que prend le processus DB ET combien (le cas échéant) wa% de temps la machine affiche.

Si top vous affiche TOUT temps, cela signifie que votre base de données est liée aux E / S et vous devrez probablement prendre en compte plusieurs machines DB (fragments) ou envisager de lancer des SSD sur la machine hôte.

C'est ça; votre recherche s'arrête là. Peu importe la quantité de CPU prise par la base de données ou la saturation de votre client d'application. si vous rencontrez des problèmes de latence d'E / S sur la base de données hôte, c'est aussi rapide que cela ne vous ira JAMAIS.

CONSEIL Si des modifications matérielles sont hors de question, selon le système de fichiers que vous exécutez (Linux), vous pouvez essayer de désactiver la journalisation ou l'écriture de métadonnées pour la base de données afin d'améliorer légèrement les performances au niveau du système de fichiers. Vous pouvez faire quelque chose de similaire sur NTFS, mais cela ne vous donnera qu'un petit coup de pouce. Ce ne sera pas 2x.

Maintenant, deuxièmement ...

Supposons que vous n'ayez presque pas eu de temps, mais que votre processeur est entièrement lié au processus DB. Votre seule option est maintenant d'introduire plus de machines DB (fragments) et de diviser le travail.

Encore une fois, vous avez terminé vos recherches si tel est le cas. Rien de ce que vous pouvez faire pour modifier le CPU pour aller plus vite.

Enfin, troisième chose ... troisième ...

Disons que la DB ne fait pas grand-chose. Ensuite, accédez à la machine cliente exécutant l'insertion par lots et vérifiez la charge du processeur - est-elle liée? Si c'est le cas, lancez quelques autres machines en faisant exactement les mêmes insertions par lots et voyez si vous pouvez obtenir une rampe linéaire.

Si le CPU n'est pas arrimé, lancez quelques threads supplémentaires sur la même machine jusqu'à ce qu'il soit arrimé et voyez comment la base de données évolue.

Je pense que vous avez peut-être déjà essayé cela, donc je suppose que votre hôte client était déjà ancré (et plus de threads ne feront pas de différence) ou que la base de données atteignait déjà sa limite et ne peut pas évoluer plus loin.

Addenda

Faire des insertions brutes sur une table non indexée qui ne contient pas de déchets est essentiellement une opération APPEND qui devrait aller aussi vite que le disque peut gérer les écritures.

Créer plus de tables sur la même machine hôte ne va pas aider, si cela augmente votre recherche de disque (pour accéder aux autres tables du disque pour y ajouter) et ralentira les choses.

Il est essentiel de comprendre ce goulot d'étranglement d'abord, puis nous pouvons optimiser l'enfer hors de lui.

J'espère que cela pourra aider! Tenez-nous au courant.


2
Pourquoi n'avez-vous pas mentionné awr ou statspack?
Philᵀᴹ

Avec un indice d'ajout, tous ces threads sauf un vont être inactifs en raison du verrouillage exclusif. Je ne pense pas que ce code soit à un stade d'efficacité où un réglage au niveau du système est nécessaire - c'est la méthodologie elle-même qui est défectueuse.
David Aldridge

En réfléchissant plus loin, je pense que votre approche présente un défaut fondamental. Si Viktors a essayé la méthode d'insertion par lots à un seul thread et a eu des temps d'attente d'E / S, cela pourrait être dû à une méthode d'insertion inefficace et à une sur-validation (attente de synchronisation des fichiers journaux). L'étape la plus importante devrait être de comprendre les mécanismes Oracle et de choisir le plus approprié en premier, sûrement?
David Aldridge

@DavidAldridge Viktors a précisé qu'il avait désactivé la journalisation (et les indices) étant donné que je supposais qu'il n'y avait pas grand-chose d'autre que la base de données faisait en plus de diffuser les données insérées directement dans le fichier de la table, c'est pourquoi je lui ai demandé de regarder directement Attente d'E / S. Peut-être qu'Oracle fait plus qui devrait / pourrait être désactivé - c'est un bon point d'investigation, je ne connais pas assez bien les profondeurs d'Oracle pour y aider malheureusement.
Riyad Kalla

4

L'invocation de l'insertion de chemin direct avec l'indicateur d'ajout entraîne la prise d'un verrou exclusif sur la table entière, donc le fait d'avoir plusieurs threads effectuant l'insertion n'aidera pas. Vous devez explicitement adresser une partition différente à chaque insertion ...

insert /*+ append */ into my_table partition (partition_name_1) ...

... pour obtenir des verrous exclusifs au niveau de la partition. Vous ne pourrez pas le faire avec une table partitionnée à la date d'insertion, très probablement, mais vous pouvez utiliser le partitionnement composite (pas le sous-partitionnement) pour obtenir plusieurs partitions par plage unique de dates d'insertion.

Ne vous engagez pas au milieu des insertions, juste à la fin.


Dois-je mentionner explicitement le nom de la partition dans la requête? J'ai une colonne, une sorte de type d'événement. Je vais essayer de partitionner par groupe d'événements et de faire en sorte que chaque thread insère un lot de lignes uniquement de type particulier
dérive

Pour éviter un verrou exclusif au niveau de la table, oui.
David Aldridge

L'indicateur APPEND doit être ignoré par Oracle pour les insertions sur une seule ligne. La description du processus par l'OP semble impliquer des insertions sur une seule ligne par lots. Je ne sais pas comment ils sont traités. Je suppose que non APPEND mais il a besoin de quelques tests.
Vincent Malgrat

Hmmm, je n'y ai pas pensé - c'est encore pire, si c'est le cas.
David Aldridge

Vaut-il la peine d'essayer des insertions à plusieurs lignes avec l'indication APPEND? Alors, combien d'entrées par insertion sur plusieurs lignes dois-je envoyer?
dérive
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.