J'ai un problème avec la planification des requêtes de PostgreSQL 9.6. Ma requête ressemble à ceci:
SET role plain_user;
SELECT properties.*
FROM properties
JOIN entries_properties
ON properties.id = entries_properties.property_id
JOIN structures
ON structures.id = entries_properties.entry_id
WHERE structures."STRUKTURBERICHT" != ''
AND properties."COMPOSITION" LIKE 'Mo%'
AND (
properties."NAME" LIKE '%VASP-ase-preopt%'
OR properties."CALCULATOR_ID" IN (7,22,25)
)
AND properties."TYPE_ID" IN (6)
J'ai la sécurité au niveau des lignes activée pour les tables utilisées ci-dessus.
avec
set enable_nestloop = True
, le planificateur de requêtes exécute la jonction de boucles imbriquées avec un temps d'exécution total d'environ 37 secondes: https://explain.depesz.com/s/59BRavec
set enable_nestloop = False
, la méthode Hash Join est utilisée et le temps de requête est d'environ 0,3 sec: https://explain.depesz.com/s/PG8E
Je l'ai fait VACUUM ANALYZE
avant d'exécuter les requêtes, mais cela n'a pas aidé.
Je sais que ce n'est pas une bonne pratique set enable_nestloop = False
et aucune autre option similaire pour le planificateur. Mais comment "convaincre" le planificateur d'utiliser des jointures de hachage sans désactiver les boucles imbriquées?
La réécriture de la requête est une option.
Si j'exécute la même requête sous un rôle qui contourne RLS, alors elle est exécutée très rapidement. La politique de sécurité au niveau des lignes ressemble à ceci:
CREATE POLICY properties_select
ON properties
FOR SELECT
USING (
(
properties.ouid = get_current_user_id()
AND properties.ur
)
OR (
properties.ogid in (select get_current_groups_id())
AND properties.gr
)
OR properties.ar
);
Toutes les idées ou suggestions seraient grandement appréciées.
la source
AND properties."TYPE_ID" IN (6);
et non= 6;
?Réponses:
Ce qui se passe ici, c'est que la boucle imbriquée est loin d'un côté. Les boucles imbriquées fonctionnent très bien lorsqu'un côté est très petit, comme le retour d'une ligne. Dans votre requête, le planificateur cherche ici et estime qu'une jointure par hachage ne renverra qu'une seule ligne. Au lieu de cela, cette jointure de hachage (property_id = id) renvoie 1 338 lignes. Cela force 1 338 boucles à s'exécuter de l'autre côté de la boucle imbriquée qui compte déjà 3 444 lignes. C'est un sacré lot quand vous n'en attendez qu'un (ce qui n'est même pas vraiment une "boucle"). Quoi qu'il en soit ..
Un examen plus approfondi à mesure que nous avançons montre que la jointure par hachage est vraiment altérée par les estimations qui en découlent,
PostgreSQL s'attend à ce que cela renvoie une ligne. Mais ce n'est pas le cas. Et c'est vraiment votre problème. Donc, certaines options ici, qui n'impliquent pas de retirer un marteau et de désactiver
nested_loop
Vous pouvez ajouter un ou deux index
properties
pour l'aider à potentiellement ignorer entièrement l'analyse séquentielle, ou mieux estimer le rendement.Alternativement, vous pouvez déplacer le contenu des propriétés vers un CTE ou une sous-sélection avec
OFFSET 0
laquelle crée une clôture.la source