Il s'agit de trois sélectionnes différentes en utilisant la même sous-requête. Comment puis-je utiliser le résultat de la sous-requête au lieu de faire une sous-requête à nouveau.
SELECT * FROM Address WHERE address_key IN ( SELECT address_key FROM person_address WHERE peson_key IN (person_list) ); -- person_list := '1,2,3,4' SELECT * FROM Phone WHERE phone_key IN ( SELECT address_key FROM person_address WHERE peson_key IN (person_list) ); SELECT * FROM Email WHERE address_key IN ( SELECT address_key FROM person_address WHERE peson_key IN (person_list) );
3 Réponses :
Vous pouvez créer une vue matérialisée pour cette requête: ou créer une table temporaire et le peupler: p> , Mais, vraiment, si vous indexez votre puisque vous avez Cela signifie que vous devez stocker ces valeurs quelque part, que ce soit la mémoire, la mémoire temporaire ou un espace de table permanent. P> mais les valeurs dont vous avez besoin sont déjà stocké dans le Utilisation de la sous-requête Il s'agit d'une question de microsecondes. P> Bien sûr, la table temporaire ou une vue matérialisée serait un peu plus efficace, mais changer le temps de sous-requête de person_key code>, il est correct pour réutiliser la sous-requête. p>
3 code> des requêtes distinctes, vous avez besoin de vos valeurs à être visible à une manière ou une autre. p>
person_address code>, tout ce dont vous avez besoin est de les récupérer. p>
3 code> impliquera
12 code> Index scans pour aller chercher le
Rowid code> S de l'index sur
Person_Key CODE> et
12 code> Table
Rowid code> Recherche pour aller chercher
adresse_key code> de la table. Ensuite, très probablement une table de hachage code> sera construite sur eux. P>
100 code> microsecondes vers
50 code> en vaut la peine, à condition que les requêtes principales puissent prendre des minutes. P> < / p>
+1 ou l'idée GTT - surtout si la logique de remplissage est plus compliquée ou prend du temps que dans l'exemple ici.
Utilisez la clause avec la clause. Je n'ai pas ré-créé votre problème exemplaire exact, mais un nombre quelconque de sous-requêtes répétées peut être placée dans la clause avec puis référencée dans la requête.
WITH address_keys as ( SELECT address_key FROM person_address WHERE peson_key IN (person_list) ) Select * from table1, table2, address_keys where table1.address_key = address_keys.address_key and table2.address_key = address_keys.address_key
Avec ne renvoie pas trois ensembles de résultats comme je le souhaite. La vue créée avec la clause ne peut être utilisée que dans une requête non multiple. Je serais peut-être en train de manquer quelque chose.
Je pense que le point de Brian est de ne pas courir trois requêtes - courir une requête de l'union tous ensemble. Ce sera plus efficace de cette façon.
Bien sûr, si les trois résultats se déroule ont des motifs extrêmement différents, cela ne vous aidera peut-être pas :)
Tout d'abord, je pense que dans la plupart des cas, cette optimisation n'apporte pas d'améliorations significatives (après la première requête que les blocs de données de Person_Address seraient principalement mis en cache dans le cache tampon et donc non lus à partir du disque dur).
Cependant comme un cas étude ou pour une raison quelconque: Vous devez mettre en cache les résultats de la requête répétée et les réutiliser plus tard dans 3 sélectionne. Cela peut être réalisé par une table (Temp) ou MV ou une structure de plsql Varray. P>
Les deux premières options couvrent Quassnoi dans sa réponse, donc je ne les mentionnerai pas. Le troisième est désavantage pour indiquer à l'avance le nombre maximal de lignes à l'avance (et je ne sais pas le droit de savoir ce qui se passe lorsque vous déclarez une varrayne avec la limite supérieure de 1 m ou 1 g d'articles seulement si vous n'avez besoin que de 1k). p>