Je commence à avoir une bien meilleure compréhension de l'indexation PostgreSQL, mais j'ai rencontré un problème avec la condition OR, où je ne sais pas comment optimiser mes index pour une requête plus rapide.
J'ai 6 conditions qui, lorsqu'elles sont exécutées individuellement, semblent avoir un coût faible. Voici un exemple des requêtes simplifiées, y compris les temps de calcul du plan de requête.
(REMARQUE: Je n'ai pas affiché les plans de requête réels pour ces requêtes ci-dessous dans le but de réduire la complexité, mais elles utilisent toutes des jointures imbriquées gauches
et des analyse d'index
comme je m'y attends avec une indexation appropriée. Si nécessaire, je peux inclure les plans de requête pour une réponse plus significative.)
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions1)
LIMIT 10;
PLAN DE REQUÊTE
-------------------------------------------------------------------------------------
Limit (cost=0.25..46.69 rows=1 width=171) (temps réel=0.031..0.031 lignes=0 boucles=1)
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions2)
LIMIT 10;
PLAN DE REQUÊTE
-------------------------------------------------------------------------------------
Limit (cost=0.76..18.97 rows=1 width=171) (temps réel=14.764..14.764 lignes=0 boucles=1)
/* snip */
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions6)
LIMIT 10;
PLAN DE REQUÊTE
-------------------------------------------------------------------------------------
Limit (cost=0.51..24.48 rows=1 width=171) (temps réel=0.252..5.332 lignes=10 boucles=1)
Mon problème est que je veux combiner ces 6 conditions avec des opérateurs OR, faisant de chaque condition une possibilité. Ma requête combinée ressemble davantage à ceci :
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions1 OR conditions2 OR conditions3 OR conditions4 OR conditions5 OR conditions 6)
LIMIT 10;
Malheureusement, cela entraîne une AUGMENTATION MASSIVE du plan de requête, qui ne semble plus utiliser mes index (au lieu de cela, choisissant de faire une jointure de hachage
au lieu d'une jointure imbriquée
, et effectuant diverses analyses séquentielles
sur les analyses d'index
précédemment utilisées).
Limit (cost=142.62..510755.78 rows=1 width=171) (temps réel=30.591..30.986 lignes=10 boucles=1)
Y a-t-il quelque chose de spécial que je devrais savoir sur l'indexation concernant les conditions en OR qui améliorerait ma requête finale ?
MISE À JOUR : Si j'utilise une UNION pour chaque SELECT individuel, cela semble accélérer la requête. Cependant, est-ce que cela m'empêchera d'ordonner mes résultats si je choisis de le faire à l'avenir ? Voici ce que j'ai fait pour accélérer la requête via UNION :
EXPLAIN ANALYZE
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions1)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions2)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions3)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions4)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions5)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 ON t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions6)
LIMIT 10;
PLAN DE REQUÊTE
-------------------------------------------------------------------------------------
Limit (cost=219.14..219.49 rows=6 width=171) (temps réel=125.579..125.653 lignes=10 boucles=1)