2017-02-21 2 views
0

J'ai une grande table Oracle avec une indexation date_time champ: « DISCONNECT_DATE »Comment utiliser le champ indexé Oracle dans une requête

Quand j'utilise ce qui suit where ma requête est exécutée rapidement:

DISCONNECT_DATE > TO_DATE('01-DEC-2016', 'DD-MON-YYYY') AND 
DISCONNECT_DATE < TO_DATE('01-JAN-2017', 'DD-MON-YYYY') 

quand j'utilise ce qui suit where ma requête est exécutée (très) lentement:

extract(month from disconnect_date) = '12' and 
extract(year from disconnect_date) = '2016' 

Ils sont à la fois plus ou moins équivalents dans leurs intentions. Pourquoi le premier travail et le dernier pas? (Je ne pense pas avoir ce problème dans SQL Server)

(J'utilise PL SQL Developer pour écrire la requête)

+0

je suppose que Oracle ne peut pas convertir automatiquement à partir de votre deuxième option à la première option, il analyse complète. Il faudrait un cas particulier pour cette optimisation. PS. Ils ne sont pas équivalents sauf si vous changez> à> = –

+0

Je suis confus. Voulez-vous dire que dans SQL Server, les deux versions s'exécutent très rapidement? Je ne sais rien à propos de SQL Server, mais je trouverais cela très surprenant. (Sauf si vous avez déjà des index basés sur des fonctions dans SQL Server, comme Gordon montre dans sa réponse.) – mathguy

Répondre

4

La question est l'utilisation des index. Dans la première, toutes les fonctions sont du côté "constant", pas du côté "colonne". Ainsi, Oracle peut facilement voir qu'un index peut être appliqué.

La logique qui fait l'indexation, cependant, ne comprend pas extract(), donc l'indice ne soit pas utilisé. Si vous souhaitez utiliser cette construction, vous pouvez créer un index sur des appels de fonctions:

create index idx_t_ddyear_ddmonth on t(extract(month from disconnect_date), extract(year from disconnect_date)); 

Note: extract() renvoie un nombre pas une chaîne, de sorte que vous devriez vous débarrasser des guillemets simples. Le mélange de types de données peut également perturber l'optimiseur.

+0

Que voulez-vous dire par côté « constant » côté par rapport à « colonne ». Avez-vous un exemple où être d'un côté ou de l'autre fait la différence pour Oracle? J'avais toujours supposé que ça ne faisait aucune différence. –

+0

@WW - pas les côtés comme dans la gauche contre la droite; vous pouvez inverser les termes afin que la référence "colonne" soit sur la droite de l'opérateur (en changeant aussi l'opérateur pour garder la même logique si nécessaire). Cela fait référence à des données provenant d'une colonne, directement ou avec manipulation (comme un appel de fonction, qui est le problème ici), étant comparé avec une expression non-colonne. Quel que soit le côté de chacun. [Lire la suite] (https://docs.oracle.com/database/121/SQLRF/sql_elements002.htm#SQLRF00214), notant le deuxième point, et la section sur les règles régissant les conversions de types de données implicites :. –

+0

@WW - S'il vous plaît prêter une attention particulière à ce que Gordon a dit dans le dernier paragraphe (à propos de faire correspondre correctement les types de données de vos expressions). Il est 100% droit - Je suis prêt à parier plus d'efficacité est perdue (globalement sur toutes les requêtes qui fonctionnent sur toutes les bases de données dans le monde) en raison de la négligence en ce qui concerne les types de données, qu'en raison de l'utilisation des fonctions autour des valeurs de la colonne (comme 'extract() 'dans votre exemple). Bonus ++ à Gordon pour avoir pris le temps de faire valoir ce point! – mathguy