Sous quelles conditions ROWNUM=1 augmenter de manière significative les performances d'une “existe” syle requête
J'ai lu quelques éléments de la discussion dans cette question et je me suis dit que dans mon code PL/SQL, j'ai "existe" style requêtes de tous sur la place qui n'utilisent pas le ROWNUM=1 optimisation.
Les questions que j'ai sont:
- L'introduction de ROWNUM=1 augmenter de manière significative la performance?
- Si oui, sous quelles conditions serait en particulier l'amélioration de la performance de l'e.g beaucoup de jointures, les contraintes non indexées sur des colonnes, des tables de grande taille, grands ensembles de résultats)
Je suis en train de déterminer de il vaut la peine de réécrire toutes mes requêtes existantes pour ajouter un ROWNUM=1 optimisation.
Les questions que je pense sont ceux qui peuvent avoir plusieurs jointures et peut demander des grandes tables. Ils ont la forme générale d':
SELECT 1
INTO ln_count
FROM table_1, table_2...., table_n
WHERE <various joins and conditions>;
IF ln_count > 0 THEN
<do stuff>
END IF;
J'envisage de les changer:
SELECT 1
INTO ln_count
FROM table_1, table_2...., table_n
WHERE <various joins and conditions>
AND ROWNUM = 1;
IF <local variable> > 0 THEN
<do stuff>
END IF;
- Est-ce votre première requête destinée à avoir SELECT COUNT(1) plutôt que de SÉLECTIONNER 1?
- SÉLECTIONNEZ l'option 1 (j'.e sélectionnez une valeur constante pour toutes les lignes retournées plutôt que de compter le nombre de lignes)
Vous devez vous connecter pour publier un commentaire.
Il permet d'améliorer les performances de façon significative (plusieurs dizaines de pour cent en moyenne) sur des requêtes qui ne peuvent être résolus par la simple recherche d'index par exemple, les jointures de table.
Cependant, il a un potentiel de cacher des données/de l'application d'erreur.
Permet d'avoir une table:
--intentionnellement n'utilisez pas PK pour prendre l'exemple le plus simple possible. Le rembourrage est utilisé pour simuler le chargement des données dans chaque enregistrement
avec un nombre d'enregistrements:
Maintenant, si vous demandez quelque chose comme
la DB doit parcourir toute la table s'il a trouvé le seul enregistrement correspondant dans le premier bloc de données (qui, par la façon dont nous ne savons pas, car il pourrait être insérées par de nombreuses façons différentes) ou dans la dernière. C'est parce qu'il ne sait pas qu'il existe un seul enregistrement correspondant. D'autre part, si vous utilisez ... et rownum = 1 que l'on peut arrêter la traversée par le biais de données après l'enregistrement est trouvé, parce que vous lui avez dit qu'il n'y est pas (ou ne sont pas nécessaires) un autre enregistrement correspondant.
L'inconvénient est que, avec le numéro de rangée de contrainte, vous pouvez obtenir undeterministic résultats si les données contiennent plus d'un enregistrement.
Si la requête a été
alors je peut recevoir à partir de la DB de la réponse 1 et 3 ainsi que 123 ... l'ordre n'est pas garanti et cela est la conséquence. (sans le numéro de rangée de la clause, je voudrais obtenir un TOO_MANY_ROWS exception. Il dépend de la situation qui est pire)
Si vous voulez vraiment requête qui teste l'existence puis l'ÉCRIRE de CETTE FAÇON.
Une règle de base de l'optimisation est de ne pas le faire, sauf si vous avez un point d'accès vous avez besoin pour réparer. Toutefois, si vous êtes curieux de connaître les avantages de performance, vous pourriez faire quelques tests en utilisant à la fois pour voir si vous pouvez mesurer toute amélioration de la performance.
wikipedia cite Donald Knuth en disant:
Je vais deviner que cela ne va pas être utile de votre temps. Moderne optimiseurs sont très bons dans ce qu'ils font donc, je l'avais trouvé un peu étonnant qu'une requête qui seul est AUTORISÉ à retourner une ligne va voir un gain de performances significatif à partir de l'ajout de ROWNUM=1.
Est le gain de performances soi-disant de la suppression de la nécessité de vérifier cette contrainte?
Je trouve quand je ne fait plus confiance à l'optimiseur j'ai souvent creuser moi-même une meilleure grave 😉
En outre:
En cas de doute de l'essayer. Trouver une grande joindre, exécuter plusieurs fois sans rownum=1, à plusieurs reprises, avec rownum=1 et de voir si vous remarquez un grand pourcentage d'amélioration. Pour s'assurer qu'il n'existe pas de problèmes de mise en cache, je suggérerais de faire cela sur une base de données que vous êtes en mesure de le redémarrer.
Bien que j'aime le plus voté réponse, dans un effort pour éviter les exceptions, je fais quelque chose comme ceci:
Ce sera toujours retourner une seule ligne avec un 1 ou un 0. Pas d'exceptions.
Note également l'utilisation de SELECT NULL. Ce qui fait un couple de choses; lorsque l'optimiseur pense que c'est approprié, Oracle seuls indices. Si vous mettez des colonnes de la table dans la clause SELECT, et les colonnes ne sont pas partie d'un indice, Oracle va faire l'index de recherche, puis prenez la ligne de la table, qui peut être totalement inutile en fonction de la requête. Puisque vous êtes seulement la vérification de l'existence d'une ligne, vous n'avez probablement pas besoin de données réelles.
SÉLECTIONNEZ la valeur NULL n'est pas de renvoyer des données (optimisation), et la clause EXISTS regarde si une ligne est renvoyée, pas les données de la ligne.
Si vous demandez COUNT(1) puis Oracle devez trouver toutes les lignes correspondantes pour satisfaire votre réponse exacte.
Si vous demandez 1 de la première ligne, Oracle peut arrêter une fois qu'il a trouvé une ligne correspondante.
Il est de bonne pratique de demander seulement pour les données que vous avez réellement besoin. Pourquoi s'Oracle pour vous dire il y a 1,203,499 résultats correspondant lorsque vous ne se soucient que le premier? Les gens ont mentionné que l'optimiseur peut améliorer les choses. Cependant, il a encore de répondre à la question que vous avez demandé. Si vous demandez à un plus facile question, il peut trouver la réponse plus rapide.
La fois, il est susceptible d'avoir un impact significatif sur les performances:-
* Le nombre réel d'enregistrements que vous trouvez est élevé,
* Oracle commutateurs à partir d'une JOINTURE de HACHAGE plan pour une BOUCLE IMBRIQUÉE, et la boucle imbriquée est le meilleur plan pour trouver la première ligne
Il peut faire une différence très significative. Si vous êtes uniquement intéressé par la première ligne de la base de données arrive à trouver lors de l'exécution de la requête, alors il est préférable de dire à Oracle qui, par adjonction de "ROWNUM=1". Si vous ne le faites pas, Oracle va supposer que vous avez l'intention de récupérer toutes les lignes de la requête par la suite, et permettront d'optimiser la requête en conséquence.
Dans le cas de COUNT(), si vous voulez savoir si il existe au moins un enregistrement, la requête de l'optimiseur de ne pas savoir qui et comptera chaque et chaque ligne - une perte de temps. Si vous ajoutez ROWNUM=1, vous avez donné l'optimiseur de la chance de s'arrêter dès qu'il trouve une ligne.
Plus les données de la requête doit labourer pour répondre à votre requête, plus la ROWNUM=1 prédicat est susceptible d'améliorer les performances. Dans un multi-jointure de table, par exemple, l'ajout ROWNUM=1 pourrait changer le plan de l'aide de beaucoup de cher les jointures de hachage, pour rendre l'utilisation de boucles imbriquées au lieu de cela, qui sont beaucoup plus rapidement lorsque les lignes existent.