preparedstatement java avec like %, lenteur de la requête
voici une expérience qui permet de mettre en évidence mon problème :
a)
la table table1 contient 1 index sur la clé primaire id et 1 index sur le champ ch1
on exécute la requête suivante :
select * from table1 where id like ? and ch1 like ?
st.setString(1,"4256")
st.setString(2,"45281226600024")
-> cette requête est très rapide (moins de 1 seconde)
le plan d'exécution de cette requête passe par l'index sur la clé primaire id
ensuite on exécute une 2ème requête:
select * from table1 where id like ? and ch1 like ?
st.setString(1,"%")
st.setString(2,"45281226600024")
-> cette requête est très lente (+ de 1 minute)
explication : le plan d'exécution de cette requête passe toujours par l'index sur la clé primaire id et donc il parcourt toute la table
pour trouver le bon ch1.
b)
on poursuit l'expérience soit sur une autre base identique soit on attend le lendemain pour
être sûr que le cache oracle a supprimé tous les statements
select * from table1 where id like ? and ch1 like ?
st.setString(1,"%")
st.setString(2,"45281226600024")
-> cette requête est très rapide (moins de 1 seconde)
le plan d'exécution de cette requête passe par l'index sur le champ ch1
on vient donc de mettre en évidence que le plan d'exécution se calcul en fonction des paramètres que l'on passe
lors de la première exécution de la requête.
c)
jusqu'à présent tout est claire
maintenant la suite de l'expérience n'a pour moi pas d'explication satisfaisante :
je change de base (base identique) ou j'attends le lendemain pour
être sûr que le cache oracle a supprimé tous les statements
select * from table1 where id like ? and ch1 like ?
st.setString(1,"%")
st.setString(2,"45281226600024%")
-> cette requête est très lente (+ de 1 minute)
après vérification, le plan d'exécution utilise la clé primaire id et donc
oracle doit parcourir toute la table pour trouver le bon ch1.
conclusion:
la différence de comportement entre l'expérience b et c
montre que lorsqu'un champ se recherche via un like avec %, alors systématiquement oracle ne passe pas par l'index de ce champ
d)
dernière expérience pour montrer que le comportement des statements et des preparedstatements est différent
je change de base (base identique) ou j'attends le lendemain pour
être sûr que le cache oracle a supprimé tous les statements
select * from table1 where id like "%" and ch1 like "45281226600024%"
-> cette requête est rapide (moins de 1 seconde)
après vérification le plan d'exécution montre que l'index utilisé est celui sur le champ ch1
conclusion:
on voit bien qu'avec un statement oracle choisi le plan d'exécution adéquat.
Question :
pourquoi oracle ignore le champ ch1 dans le choix de l'index dès lors que l'on utilise % pour ce champ?
je en vois pas l'intérêt d'ignorer ce champ quand on utilise un %.
et pourquoi le calcul de plan d'exécution est différent entre un statement et un preparedstatement ?
ce comportement est très embêtant car il conduit à dégrader énormément les performances pour ce genre de requête.