2 votes

Oracle compte (*) prend trop de temps

J'essayais de récupérer le count(*) de la table, qui contient presque 7 millions d'enregistrements et cela prend plus d'une heure pour retourner le résultat.

De plus, la table a 153 colonnes dont un index a été créé pour la colonne 123, donc j'ai essayé de lancer la requête suivante en parallèle, mais cela n'a pas aidé.

sélectionner /*+ parallel (5) */ count(123) from 

Merci de suggérer s'il y a une autre manière.

Quand j'ai exécuté desc sur la table dans Toad, l'onglet index contient la valeur du nombre de lignes. Avez-vous une idée de comment cette valeur est mise à jour là-bas?

4voto

David Aldridge Points 27624

Quelques points à mentionner :

  1. Pour que "select count(*) from table" utilise un index, la colonne indexée doit être non nulle, ou l'index doit être de type bitmap.
  2. S'il est connu qu'il n'y a pas de valeurs nulles dans la colonne mais qu'il n'y a pas de contrainte de non nullité, utilisez alors "select count(*) from table where column_name is not null".
  3. Il doit bien sûr être plus efficace de parcourir l'index plutôt que la table, mais avec autant de colonnes de table, vous êtes probablement bon de ce côté-là.
  4. Si vous voulez vraiment un balayage d'index parallèle, utilisez l'indice parallel_index, pas parallel. Mais avec seulement 7 millions de lignes, vous pourriez ne pas avoir besoin de parallélisme.
  5. Vous devez vérifier le plan d'exécution pour voir si un index et/ou une requête parallèle sont utilisés.
  6. Si vous pouvez utiliser un nombre estimé de lignes, envisagez d'utiliser la clause sample : par exemple "select 1000*count(*) from table sample(0.1)".

2voto

ntalbs Points 4583

Compter le nombre de lignes d'une grande table prend beaucoup de temps. C'est naturel. Certains SGBD stockent le nombre d'enregistrements, cependant, ce type de SGBD limite la concurrence. Il faut verrouiller l'ensemble de la table avant toute opération DML sur la table. (Le verrouillage de l'ensemble de la table est nécessaire pour mettre à jour le comptage correctement.)

La valeur dans ALL_TABLES.NUM_ROWS (ou USER_TABLES.NUM_ROWS) est juste une information statistique générée par la procédure analyze table ... ou dbms_stats.gather_table_stats. Ce n'est pas une information précise, ni en temps réel.

Si vous n'avez pas besoin du nombre exact de lignes, vous pouvez utiliser l'information statistique. Cependant, vous ne devriez pas en dépendre. Elle est utilisée par l'optimiseur Oracle, mais ne devrait pas l'être dans le programme d'application.

Je ne suis pas sûr pourquoi vous devez compter le nombre de lignes de la table. Si vous en avez besoin dans le programme par lots qui est exécuté rarement, vous pouvez partitionner la table pour augmenter le parallélisme. Si vous avez besoin du compte dans un programme en ligne, vous devriez trouver un moyen de ne pas utiliser le compte.

0voto

APC Points 69630
sélectionner /*+ parallèle (5) */ 

Il semble que le nombre impair pour le degré de parallélisme. Eh bien, 5 est évidemment un nombre impair, et c'est étrange. Les DoP devraient être un multiple de deux (voir ci-dessous pour plus d'informations).

Quoi qu'il en soit, avez-vous une raison d'utiliser une requête parallèle ? Avez-vous au moins cinq processeurs de rechange ? Sinon, il y a de fortes chances que les frais généraux de gestion des esclaves PQ contribuent au moins à la mauvaise performance.


Pourquoi DOP = n*2 ? Il existe une heuristique établie basée sur la théorie des files d'attente selon laquelle l'exécution de plus de deux tâches en lot simultanément entraîne une dégradation des performances. En savoir plus. (Je pense que la théorie des files d'attente recommande en réalité un chiffre de 1,8, mais comme les tâches de base de données sont souvent limitées par l'E/S ou le disque, nous pouvons généralement opter pour 2.)

J'ai dit à l'origine "puissance de 2", mais c'est principalement parce que les serveurs multicœurs ont tendance à avoir un certain nombre de processeurs qui est une puissance de 2, mais un multiple de 2 est plus précis, car certaines boîtes ont 12 processeurs ou un autre nombre.

Alors, si nous avons une boîte à 64 cœurs, un DOP de 5 ou 37 convient, car nous avons suffisamment de processeurs pour exécuter autant de threads simultanément. Mais si nous avons une petite boîte quadricœur, seuls 2, 4 ou 8 ont du sens, car ce sont les seules valeurs qui garantiront une distribution uniforme du travail sur les quatre processeurs. Exécuter cinq threads sur une boîte quadricœur signifie qu'un processeur fera beaucoup plus de travail que les trois autres; il est possible qu'il mette plus de temps à terminer, laissant les trois autres esclaves en attente. Ainsi, DOP=5 peut en réalité entraîner un temps écoulé plus long que DOP=4.

DOP=n*2 n'est qu'une règle empirique, et non gravée dans le marbre. Cependant, elle repose sur un raisonnement solide, et nous devrions savoir pourquoi nous faisons quelque chose de différent. De toute évidence, nous devrions avoir mené des expériences pour confirmer que nous avons choisi le bon DOP (quelle que soit la valeur sur laquelle nous nous arrêtons).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X