9
votes

Oracle Requête en utilisant "J'aime" sur la colonne Numéro indexée, de mauvaise performance

sur la requête 1 Une analyse de la table complète est en cours d'exécution même si l'identifiant est une colonne indexée. La requête 2 atteint le même résultat mais beaucoup plus rapide. Si la requête 1 est exécutée, renvoie une colonne indexée, elle revient rapidement, mais si les colonnes non indexées sont renvoyées ou que toute la ligne est alors la requête prend plus de temps.

dans la requête 3 Il fonctionne vite, mais la colonne "Code" est un Varchar2 (10) au lieu d'un nombre (12) et est indexé de la même manière que "ID". P>

Pourquoi la requête 1 ne pas ramasser qu'il devrait utiliser l'index? Y a-t-il quelque chose qui devrait être changé pour permettre aux colonnes numériques indexées d'effectuer plus rapidement? P>

[Query 1] P>

select a1.*
from people a1
where a1.code like '119%' 
and rownum < 5


3 commentaires

Merci pour le bon formatage!


Votre accueil j'aime lire Jolie formatage moi-même.


Vous devriez envisager d'utiliser la méthode dbms_xplan.display de récupération du plan d'explication vraiment. Il est beaucoup plus utile et montre l'application des prédicats et des jointures à différentes étapes de l'exécution.


5 Réponses :


0
votes

Essayez de placer une indice dans l'une de vos requêtes pour le forcer à utiliser l'index souhaité, puis vérifiez votre plan: il pourrait s'agir de (en raison de la biais de biais ou autre) L'optimzeur fait prend l'index en compte, mais décide de l'utiliser à cause du coût perçu.


2 commentaires

Depuis que OP ne comprend pas les index, je ne recommanderais pas d'utiliser des indices.


Nous avons essayé d'utiliser un indice qui obligeait l'index à utiliser et a abouti à un résultat rapide, mais nous ne pourrons pas pouvoir utiliser des notes de notre frontend. La requête 3 montre que lorsque la même chose est effectuée sur une colonne Varchar2 fonctionne bien sans indices. J'aimerais trouver une solution qui ne nécessite pas de notes. Une modification de la table serait possible (sauf pour changer le type de colonne).



1
votes

Optimizer a décidé qu'il est plus rapide de faire une balayage de table, probablement en raison du faible nombre d'enregistrements réels.

En outre, vous devez savoir que la correspondance non exacte est toujours pire que exactement. Si votre où était "A1.Id =" 123456 "", il utiliserait probablement l'index. Mais encore une fois, même l'index prend deux lectures (trouvez d'abord un enregistrement dans l'index, puis lisez le bloc de la table) et pour les très petites tables qu'elle pourrait décider de la numérisation de table.


3 commentaires

La table a des rangées de 200K.


En raison du prédicat RWOWLUM, la requête ne sera pas nécessairement complète de balayer toute la table. Il s'arrêtera quand il trouve le nombre approprié de lignes.


Expliquer le plan sur la requête 1 montre qu'il existe une table complète avec le rownum.



-3
votes

Le comme code> Le mot clé dit à SQL que vous effectuez une correspondance d'expression régulière. Vous ne devez jamais utiliser des expressions régulières dans SQL ou dans une bibliothèque de programmation jusqu'à ce que vous ayez vérifié les fonctions de chaîne disponibles pour voir si la requête pouvait être exprimée simplement avec elles. Dans ce cas, vous pouvez modifier cela en une condition égale en comparant uniquement la sous-chaîne constituée des 3 premiers caractères du code. À Oracle, cela ressemblerait à:

SELECT *
FROM people
WHERE SUBSTR(code,1,3) = '119'


7 commentaires

Je pense que j'ai raison de dire que les index basés sur des fonctions à Oracle (tels que l'utilisation de l'enveloppe supérieure, des substrings et autres) ne sont disponibles que dans la version Enterprise: qui peut ne pas toujours être une option.


Votre requête en utilisant le substruisier effectue une analyse de la table complète. Nous utilisons comme non pas plus de regreçon.


Les index basés sur la fonction sont pris en charge dans l'édition standard depuis 10g si je ne me trompe pas. L'index de la fonction substr + est probablement la meilleure solution.


Comme n'est pas une fonction d'expression régulière. La ferme est regexp_instr. Et une sous-chaîne n'est pas plus susceptible d'utiliser un indice que similaire.


Comme n'est pas une correspondance d'expression régulière, il est clair [motif correspondant] [1]. Vous l'avez confondu avec [REGEXP_LIQue] [2] [1]: download.oracle.com/docs/cd/b19306_01/server.102/b14200/... [2]: Download.Oracle.com/docs/cd/b19306_01/Server.102/b14200/...


Je n'ai pas confondu avec Regexp_ike. Dans n'importe quel SQL, comme une correspondance d'expression régulière, il utilise simplement un moteur d'expression régulier simple et limité contrairement au plus récent Regexp_like qui utilise un moteur d'expression régulier complet. Les deux formes de similaire correspondent à la correspondance. Les deux formes d'une manière d'utiliser des expressions régulières. Mais le formulaire le plus récent a une mise en œuvre plus complète d'expressions régulières que similaires. L'essentiel est que la correspondance de motif est plus coûteuse et plus complexe en matière d'analyse du plan d'exécution.


@Michael pouvez-vous récupérer cela avec des exemples? J'ai essayé 100 000 opérations SUBSTR () contre 100 000 goûts équivalents et comme environ 30% plus vite.



4
votes

Comme est une fonction de chaîne, un index numérique ne peut donc pas être utilisé aussi facilement. Dans l'indice numérique, vous aurez 119,120,130,130,130,130,13,13,193 ..., 11921 11922 ... etc., c'est-à-dire que toutes les lignes commençant par le «119» ne seront pas au même endroit, Donc, l'indice entier doit être lu (d'où la balayage complète rapide). Dans un index basé sur le personnage, ils seront ensemble (par exemple, '119', '1191', '11911', '120', ...) Donc, une meilleure gamme peut être utilisée.

Si vous recherchez des valeurs d'identification dans une plage particulière (par exemple 119000 à 119999), spécifiez-le comme le prédicat (ID entre 119000 et 119999).


0 commentaires

14
votes

2 commentaires

Il pourrait également être possible de réécrire le prédicat comme ID entre 1190000 et 1199999, si les valeurs sont toutes du même ordre de grandeur. Ou s'ils ne sont pas alors id = 119 ou ID entre 1190 et 1199, etc ..


Merci c'était une explication très complète et j'ai apprécié vos solutions énumérées. L'index basé sur la fonction semble fonctionner bien.