web-dev-qa-db-fra.com

Performance Oracle à la date de la plage de date

J'essaie de compter le nombre de commandes passées par une certaine organisation sur une certaine gamme de temps. Mais j'ai constaté que la requête ci-dessous (gamme de temps de 2 jours) est beaucoup plus lente qui fait deux requêtes séparées chaque jour.

 SELECT COUNT(*)  FROM ORDER_HISTORY
 WHERE organization = 'BA' AND  TIMESTAMP > = TO_DATE('2016-01-05', 'YYYY-MM-DD') 
 AND TIMESTAMP<= TO_DATE('2016-01-05', 'YYYY-MM-DD')+2;

J'ai un index sur la colonne timestamps et un autre index sur la colonne organization

enter image description here

Voici le schéma de ma table. La colonne timestamp est de type DATE.

enter image description here

Le plan d'exécution de la requête sur 2 jours utilise l'index sur organization:

enter image description here

Le plan d'exécution de la requête sur 1 jour utilise l'index sur timestamp:

enter image description here

Avoir des statistiques:

   SELECT COUNT(*)  FROM ORDER_HISTORY
   WHERE ORGANIZATION = 'BA' ;

donne 2359847.

   SELECT COUNT(*)  FROM ORDER_HISTORY
   WHERE TIMESTAMP > = TO_DATE('2016-01-05', 'YYYY-MM-DD')
   AND TIMESTAMP<= TO_DATE('2016-01-05', 'YYYY-MM-DD')+1;

donne 9260. Et la même requête sur 2 jours donne 16510.

Pourquoi pourrais-je obtenir le genre de comportement étrange du moteur Oracle DB?

2
Gab是好人

La raison en est que l'optimiseur basé sur les coûts a un plan en mémoire à partir d'une sélection précédente, où le nombre d'enregistrements d'une organisation donnée, à savoir "lol", était beaucoup plus petit, quelque 14 000. Lorsque le plan est en mémoire, le CBO Ne se soucie pas des valeurs de paramètre plus. Utilisation:

WHERE organization || '' = 'BA'
1
Gerard H. Pille

Il me semble que les statistiques d'optimiseur sont soit obsolètes, soit une bibliothèque de données (c'est-à-dire que vous avez une colonne populaire et impopulaire dans une colonne d'organisation). Optimizer estime que le filtre ORGANIZATION = 'BA' Retourne 14898 rangées qui sont bien différentes du résultat réel. dbms_stats.gather_table_stats devrait résoudre le problème. ** Selon la capture d'écran, il semble que "lol" est une valeur d'organisation utilisée avec EXPLAIN, je suggérerais d'afficher un plan d'exécution réel.

Vous pouvez également créer des statistiques étendues sur 2 colonnes (organisation, horodatage).

En outre, vérifiez toujours le plan d'exécution réel (dbms_xplan.display_cursor), pas le résultat de explain.

((( mise à jour

Une autre chose qui peut aider à enquêter sur le problème. Je suggère également de trouver une requête (ou des requêtes) dans v$sql/v$sqlarea et vérifier leurs coûts. Également, v$sql possède is_bind_aware et is_bind_sensitive colonnes qui indiquent si Optimizer considère et utilise différents plans dépend de différentes valeurs de variables de liaison. Autres détails sur la raison pour laquelle plusieurs plans ont été générés V$SQL_SHARED_CURSOR Vue du système qui montre pourquoi le curseur enfant existant n'a pas été partagé avec un nouveau.

1
a1ex07