Existe-t-il un moyen de forcer un ordre de jointure spécifique dans Postgres?Ordre de jointure de table dans postgres
J'ai une requête qui ressemble à ceci. J'ai éliminé un tas de choses qui étaient dans la vraie requête, mais cette simplification démontre le problème. Ce qui reste ne devrait pas être trop cryptique: En utilisant un système de sécurité de rôle/tâche, j'essaie de déterminer si un utilisateur donné a des privilèges pour effectuer une tâche donnée.
select task.taskid
from userlogin
join userrole using (userloginid)
join roletask using (roleid)
join task using (taskid)
where loginname='foobar'
and taskfunction='plugh'
Mais je réalise que le programme connaît déjà la valeur de userlogin, il semblait donc la requête pourrait être plus efficace en sautant la recherche sur userlogin et remplir seulement dans le userloginid, comme ceci:
select task.taskid
from userrole
join roletask using (roleid)
join task using (taskid)
where userloginid=42
and taskfunction='plugh'
Lorsque j'ai fait cela - en éliminant une table de la requête et en codant en dur la valeur récupérée à partir de cette table à la place - le temps du plan expliquer a augmenté! Dans la requête d'origine, Postgres lit userlogin puis userrole puis roletask puis task. Mais dans la nouvelle requête, il a décidé de lire roletask en premier, puis de se joindre à userrole, même si cela nécessitait de faire un scan complet sur roletask.
complète expliquer les plans sont les suivants:
Version 1:
Hash Join (cost=12.79..140.82 rows=1 width=8)
Hash Cond: (roletask.taskid = task.taskid)
-> Nested Loop (cost=4.51..129.73 rows=748 width=8)
-> Nested Loop (cost=4.51..101.09 rows=12 width=8)
-> Index Scan using idx_userlogin_loginname on userlogin (cost=0.00..8.27 rows=1 width=8)
Index Cond: ((loginname)::text = 'foobar'::text)
-> Bitmap Heap Scan on userrole (cost=4.51..92.41 rows=33 width=16)
Recheck Cond: (userrole.userloginid = userlogin.userloginid)
-> Bitmap Index Scan on idx_userrole_login (cost=0.00..4.50 rows=33 width=0)
Index Cond: (userrole.userloginid = userlogin.userloginid)
-> Index Scan using idx_roletask_role on roletask (cost=0.00..1.50 rows=71 width=16)
Index Cond: (roletask.roleid = userrole.roleid)
-> Hash (cost=8.27..8.27 rows=1 width=8)
-> Index Scan using idx_task_taskfunction on task (cost=0.00..8.27 rows=1 width=8)
Index Cond: ((taskfunction)::text = 'plugh'::text)
Version 2:
Hash Join (cost=96.58..192.82 rows=4 width=8)
Hash Cond: (roletask.roleid = userrole.roleid)
-> Hash Join (cost=8.28..104.10 rows=9 width=16)
Hash Cond: (roletask.taskid = task.taskid)
-> Seq Scan on roletask (cost=0.00..78.35 rows=4635 width=16)
-> Hash (cost=8.27..8.27 rows=1 width=8)
-> Index Scan using idx_task_taskfunction on task (cost=0.00..8.27 rows=1 width=8)
Index Cond: ((taskfunction)::text = 'plugh'::text)
-> Hash (cost=87.92..87.92 rows=31 width=8)
-> Bitmap Heap Scan on userrole (cost=4.49..87.92 rows=31 width=8)
Recheck Cond: (userloginid = 42)
-> Bitmap Index Scan on idx_userrole_login (cost=0.00..4.49 rows=31 width=0)
Index Cond: (userloginid = 42)
(Oui, je sais que dans les deux cas, les coûts sont faibles et la différence doesn On dirait que ce serait important, mais c'est après avoir éliminé un tas de travail supplémentaire de la requête pour simplifier ce que j'ai à poster.La vraie question n'est toujours pas scandaleuse, mais je suis plus intéressé par t . Il principe)
Pouvez-vous afficher les plans de requête (expliquer l'analyse) et les définitions de table? – hgmnz
D'accord, vous avez demandé, j'ai remplacé l'exemple hypothétique simple par la requête réelle, et j'ai ajouté les résultats du plan d'explication. Oh, je suis sûr que je pourrais ajouter quelques index supplémentaires pour accélérer la deuxième requête, mais ce n'est pas le point. Pourquoi Postgres a-t-il choisi un plan inférieur à ce qu'il pouvait faire de mieux, compte tenu des requêtes qu'il avait? Surtout quand il a démontré qu'il pourrait faire mieux si je compliquais la requête? – Jay
comparez-vous les temps d'exécution réels des requêtes ou simplement le coût global dans le plan d'explication? les coûts? notamment, vous venez de poster une sortie d'explication, pas d'expliquer l'analyse. Bien que vous vous attendiez à ce qu'un coût plus élevé équivaille à une exécution de requête plus lente, il se peut que cela ne fonctionne pas de cette façon. – araqnid