Pourquoi est-Oracle si lent lorsque je passe la java.sql.L'horodatage pour une colonne de DATE?
J'ai une table avec un DATE
colonne avec le temps (comme d'habitude dans Oracle puisqu'il n'y a pas un TIME
type). Quand j'ai une requête que la colonne de JDBC, j'ai deux options:
- Convertir manuellement les valeurs d'Oracle
to_date()
- Utiliser un
java.sql.Timestamp
Les deux approches de travail et ont des zones exclusives de hideux. Mon problème est quand je suis SELECT
ing données. Voici deux exemples de requêtes:
select *
from TABLE
where TS between {ts '2009-12-08 00:00:00.000'} and {ts '2009-12-09 00:00:00.000'}
select *
from TABLE
where TS between trunc({ts '2009-12-08 00:00:00.000'}) and trunc({ts '2009-12-09 00:00:00.000'})
Les deux requêtes de travail, les mêmes résultats et produit exactement le même résultat dans EXPLAIN PLAN
. Ce droit index sont utilisés.
Requête ne fonctionne 15 minutes, tandis que la deuxième requête prend 0.031 s. Pourquoi est-ce? Est-il un lieu central pour résoudre ce problème ou dois-je vérifier toutes mes requêtes pour cet article et de faire absolument sûr que la trunc()
est là? Comment puis-je résoudre ce problème lorsque j'ai besoin de sélectionner jusqu'à une certaine deuxième?
[MODIFIER] La table est partitionnée et je suis sur Oracle 10.2.0.
- Est votre table partitionnée? Oracle JDBC ne semble pas utiliser la partition de l'élagage lorsque vous définissez les paramètres comme Timestamp, pour des raisons que je n'ai jamais compris.
- Oui, c'est partitionnée.
- +1 j'aimerais comprendre aussi. Cela se produit uniquement sur une immense table?
- Eh bien, je suppose que vous ne remarquerez même pas avec une petite table 🙂
- Comme vous l'avez noté, à l'aide de l' {ts "} syntaxe de votre code de base de données agnostiques, mais est-il une façon de savoir ce que SQL est vraiment passé à la base de données? Et comment est-il important d'être de la base de données agnostique? Si vous pouviez poster le PLAN d'EXPLIQUER les résultats que nous pourrions être en mesure de mieux comprendre ce qui se passe.
- Bob: Expliquer le plan montre les mêmes résultats, même lorsque j'utilise TO_DATE().
Vous devez vous connecter pour publier un commentaire.
Je ne comprends pas ce que {ts '2009-12-08 00:00:00.000'} signifie réellement, car ce n'est pas Oracle SQL pour autant que je sais. Pouvez-vous montrer exactement ce que la requête est, vous êtes en cours d'exécution?
Un problème possible est que vous êtes en précisant votre gamme de millisecondes. Oracle de type DATE ne redescend de quelques secondes. (Utiliser le type TIMESTAMP si vous avez besoin de stocker des fractions de secondes). Mais ce qui se passe, c'est que dans la première requête, Oracle est la conversion de chaque JOUR de la valeur à un HORODATAGE afin de faire la comparaison de votre date précisée.
Dans le second cas, il sait TRUNC() va efficacement votre tour de valeur à quelque chose qui peut être exprimé comme une DATE, si aucune conversion n'est nécessaire.
Si vous voulez éviter de telles conversions implicites, assurez-vous que vous êtes toujours en train de comparer des choses comparables.
par exemple
{ts ...}
,{d ...}
est une fonctionnalité cachée de JDBC qui permet de spécifier un java.sql.Timestamp, java.sql.Date dans une DB agnositic façon.C'est parce que d'HORODATAGE type de données est plus précise que la DATE donc, lorsque vous fournissez des HORODATAGE valeur de paramètre dans la colonne de la DATE de la condition, l'Oracle a convertir toutes les valeurs de DATE en TIMESTAMP, pour faire une comparaison (c'est le INTERNAL_FUNCTION d'utilisation ci-dessus) et, par conséquent, l'indice doit être complète numérisée.
J'ai un problème similaire ici:
Non-négligeable de l'exécution du plan de différence avec Oracle lors de l'utilisation de jdbc de type Timestamp ou Date
Dans mon exemple, il provient essentiellement par le fait que lors de l'utilisation de JDBC de l'heure, un
INTERNAL_FUNCTION
est appliqué à la colonne de filtre, pas la lier des variables. Ainsi, l'indice ne peut pas être utilisé pourRANGE SCANS
ouUNIQUE SCANS
plus:Ces deux liaisons résultat totalement différent du comportement (pour exclure lier des variables de jeter un oeil, je me suis mise à exécution de deux dur-analyse):
1) Avec des horodatages, je reçois un
INDEX FULL SCAN
et donc un prédicat de filtre2) Avec les dates, j'ai beaucoup mieux
INDEX RANGE SCAN
et un accès prédicatLa résolution de ce problème à l'intérieur de tiers Api
Pour l'enregistrement, ce problème peut également être résolu au sein de tiers Api par exemple, en mode veille prolongée:
Ou dans jOOQ:
J'ai eu ce problème sur un projet il y a un moment et en définissant la propriété de connexion oracle.jdbc.V8Compatible=true résolu le problème.
Dougman lien vous indique comment le configurer:
Note pour 11g et cette propriété est apparemment pas utilisé.
De http://forums.oracle.com/forums/thread.jspa?messageID=1659839 :