Mes tables:
index: R2 (VAL), R1 (A), R1 (B), R1 (B) P>
Mon objectif: Obtenez tous les enregistrements de R1 où A ou B sont égaux à Val dans R2 P>
J'ai pensé à 2 options: p> ou p> dans mon cas spécifique: p> < ul>
Je voulais entendre si je peux réécrire la requête de manière meilleure afin de gagner des performances. Au fait, j'utilise pg 9.6 p> merci .. p> p>
4 Réponses :
Et que diriez-vous de
select * from r1 join r2 on r1.a=r2.val union select * from r1 join r2 on r1.b=r2.val
Cela ne semble pas bon, nécessite deux scans de SEQ sur R1 et deux analyses de hachage sur R2
Je ne suis pas d'accord avec l'Union_All - car si A et B finissent par être la même valeur, vous obtiendrez des enregistrements en double ....
Je recommanderais:
select r1.*
from r1 join
r2
on r1.a = r2.val
union
select r1.*
from r1 join
r2
on r1.b = r2.val;
Comment votre 1ère requête est-elle meilleure que la optique: Sélectionnez * à partir de R1 où existe (sélectionnez * à partir de R2 où R1.a = R2.val ou r1.b = r2.val); Code>?
@ forpas. . . Je ne sais pas comment Postgres se comporte dans l'utilisation d'index avec le ou code> dans le où la clause CODE>. Il pourrait y avoir des cas où il n'utilise pas d'index approprié.
Donc, cette requête devrait être un cas de test et non une recommandation.
@ forpas - tout ce que vous voulez l'appeler, la première requête semble être la meilleure dans la plupart des cas.
@klin existe deux fois? Je ne le pense pas. Mais, je me tromperais peut-être, c'est pourquoi je l'appelle un cas d'essai.
@forpas - Les deux Existent code> utilisent deux scannes d'index très rapides uniquement tandis que existe (... ou ...) code> Besoins bitmapor.
Selon le plan d'exécution, la première option que j'ai suggérée dans mon poste principal est meilleure. La première requête que vous avez suggérée, utilisez une analyse SEQ sur R1 et l'analyse uniquement sur R2. La deuxième requête que vous avez suggérée semble bonne dans l'aspect de la performance mais prend toujours plus de temps que ma première requête.
Par curiosité: dB <> violon.
Utilisez un CTE code> que Renvoie tous les val code> S de R2 code> (donc vous numérisez r2 code> une seule fois).
Mais peut-être que cela n'est pas nécessaire si l'optimiseur le fait déjà pour Sélectionnez Val de R2 Code>.
Ensuite, utilisez case code> pour vérifier les 2 cas distincts, de sorte que le 2e cas ( lorsque b dans (sélectionnez Val de CTE) code>) uniquement lorsque le 1er cas ( Lorsque vous êtes dans (sélectionnez Val de CTE) code>) échoue.
WITH cte AS (SELECT VAL FROM R2)
SELECT * FROM R1
WHERE 1 = CASE
WHEN a IN (SELECT VAL FROM cte) THEN 1
WHEN b IN (SELECT VAL FROM cte) THEN 1
ELSE 0
END
Il s'agit de la requête la plus proche de l'aspect de la performance s à ma première requête. Ce coût de requête est de 4658, tandis que ma première requête code> S est de 3385.
On dirait dans ce cas spécifique La première requête que j'ai suggérée dans mon commentaire principal fournit la meilleure performance: @klin a préparé un dbfiddle avec tous les plans d'exécution si quelqu'un veut avoir un regard :
https://dbfiddle.uk/?rdbms=postgres_9.5&fiddle=5B50f605262E406C0BAB13710EC121D5 < / p> p>
J'essaierais
SELECT R1. * À partir de R1 Rejoignez R2 ON (R1.A = R2.VAL ou R1.B = R2.VAL); Code> - Je ne sais pas si c'est plus rapide que tout sauf Il semble être l'expression SQL la plus propre... Sauf que cela renvoie une ligne deux fois si
a code> etb code> apparaît dansr2 code>, pour éviter que vous ayez besoin de jeter dans un < Code> distinct code>.