Oracle: comment s'assurer qu'une fonction dans la clause where ne sera appelée qu'après que toutes les clauses where restantes ont filtré le résultat?
Je suis en train d'écrire une requête à cet effet:
select *
from players
where player_name like '%K%
and player_rank<10
and check_if_player_is_eligible(player_name) > 1;
Maintenant, la fonction check_if_player_is_eligible() est lourd et, par conséquent, je veux que la requête pour filtrer les résultats de recherche suffisamment et ensuite seulement d'exécuter cette fonction sur les résultats filtrés.
Comment puis-je m'assurer que le filtrage se fait avant que la fonction est exécutée, de sorte qu'il s'exécute le nombre minimum de fois ?
source d'informationauteur Daud
Vous devez vous connecter pour publier un commentaire.
Voici deux méthodes où vous pouvez tromper Oracle en n'évaluant pas votre fonction avant tous les autres OÙ l'une des clauses ont été évaluées:
À l'aide de rownum
À l'aide de la pseudo-colonne
rownum
dans une sous-requête force Oracle pour "matérialiser" la sous-requête. Voir par exemple cet askTom fil pour des exemples.Voici la documentation de référence "Unnesting de les sous-requêtes Imbriquées":
À l'aide de CAS
À l'aide de CAS, vous pouvez forcer l'Oracle pour évaluer votre fonction lorsque les autres conditions sont évaluées à TRUE. Malheureusement, il implique la duplication de code si vous voulez utiliser d'autres clauses d'utiliser des index comme dans:
Il est le NO_PUSH_PRED astuce pour le faire sans impliquer rownum d'évaluation (qui est un bon truc de toute façon) dans le processus!
Que vous voulez généralement à éviter d'imposer un ordre spécifique d'exécution. Si les données ou la requête change, vos conseils et astuces peuvent avoir l'effet inverse. Il est généralement préférable de fournir les métadonnées utiles à l'Oracle de sorte qu'il peut prendre les bonnes décisions pour vous.
Dans ce cas, vous pouvez offrir de meilleures statistiques de l'optimiseur à propos de la fonction avec ASSOCIER LES STATISTIQUES.
Par exemple, si votre fonction est très lent car il doit lire les 50 blocs à chaque fois qu'il est appelé:
Par défaut d'Oracle suppose qu'une fonction peut sélectionner une ligne de 1/20e de l'heure. Oracle veut éliminer autant de lignes que bientôt
que possible, la modification de la sélectivité doit faire moins de chances d'être exécuté en premier:
Mais cela soulève d'autres questions. Vous devez choisir une sélectivité pour TOUTES les conditions possibles, 90% ne sera certainement pas toujours être exactes. Le IO coût est le nombre de blocs par les cheveux, mais le PROCESSEUR est "machine " instructions", qu'est-ce exactement est-ce à dire?
Il y a des moyens plus avancés pour personnaliser les statistiques,par exemple à l'aide de la De Données Oracle Cartouche Optimiseur Extensible. Mais les données de la cartouche est probablement l'un des plus difficiles les fonctionnalités d'Oracle.
Vous ne précisez pas si le joueur.player_name est unique ou pas. On pourrait supposer que c'est et puis la base de données a pour appeler la fonction au moins une fois par résultat record.
Maissi le joueur.player_name n'est pas unique, vous voulez minimiser les appels vers le bas pour count(distinct joueur.player_name) fois. Comme (Demander)Tom montre dans Oracle Magazinele sous-requête scalaire cache est un moyen efficace pour ce faire.
Vous devez emballer votre appel de fonction dans une sous-sélection afin de rendre l'utilisation de la sous-requête scalaire cache:
À l'origine de la requête dans une table dérivée puis placez le prédicat supplémentaire dans la clause where de la table dérivée.