J'ai des problèmes pour que postgres utilise mes index multi-colonnes pour une recherche complète en utilisant l'extension btree_gin. Ceci est pour une page de recherche d'articles. L'idée derrière l'utilisation de btree_gin est d'être en mesure d'obtenir le « id » champ pour le tri et magazine_id comme un filtre:Postgresql n'utilise pas d'index multi-colonnes (btree_gin)
CREATE INDEX idx_gin_search ON article USING gin(id, magazine_id, search_vector_full) WITH (fastupdate = off);
Postgres décide d'utiliser un indice de btree le magazine à la place, puis filtre (= lent) :
Executed SQL
SELECT ••• FROM article WHERE (((article.search_vector) @@
(plainto_tsquery('pg_catalog.english', 'interesting'))) AND
article.magazine_id = 7) ORDER BY article.id ASC LIMIT 36
Time 13.4780406952 ms
QUERY PLAN
Limit (cost=2021.87..2021.96 rows=36 width=384) (actual time=9.782..9.787 rows=36 loops=1)
-> Sort (cost=2021.87..2027.49 rows=2248 width=384) (actual time=9.781..9.784 rows=36 loops=1)
Sort Key: id
Sort Method: top-N heapsort Memory: 53kB
-> Index Scan using idx_magazine_id on article (cost=0.29..1952.53 rows=2248 width=384) (actual time=0.035..8.924 rows=2249 loops=1)
Index Cond: (magazine_id = 7)
Filter: (search_vector @@ '''interesting'''::tsquery)
Rows Removed by Filter: 11413
Planning time: 4.600 ms
Execution time: 9.860 ms
Alors, ce que je trouve comprendre encore moins, est qu'il refuse aussi d'utiliser ce simple indice de btree sur la page LISTE des articles, où ils sont énumérées ci-dessus x par page dans l'ordre décroissant:
CREATE INDEX idx_btree_listing ON article USING btree(id DESC, magazine_id);
Encore une fois, il ne pas utiliser l'index multi-colonnes:
Executed SQL
SELECT ••• FROM article WHERE article.magazine_id = 7
ORDER BY article.id DESC LIMIT 36
Time 1.4750957489 ms
QUERY PLAN
Limit (cost=0.29..7.48 rows=36 width=384) (actual time=0.034..0.115 rows=36 loops=1)
-> Index Scan Backward using idx_magazine_id on article (cost=0.29..2729.56 rows=13662 width=384) (actual time=0.031..0.107 rows=36 loops=1)
Filter: (magazine_id = 7)
Planning time: 1.354 ms
Execution time: 0.207 ms
EDIT: Ce qui précède est une configuration de développement avec moins de dossiers et seulement 1 le magazine, d'où la vitesse rapide. Voici un journal produit par auto_explain sur le serveur de production:
duration: 230.629 ms plan:
SELECT article.id, article.title, article.date, article.content FROM article WHERE article.magazine_id = 7 ORDER BY article.id DESC LIMIT 36
Limit (cost=0.42..43.67 rows=36 width=306) (actual time=229.876..229.995 rows=36 loops=1)
-> Index Scan Backward using idx_magazine_id on article (cost=0.42..239539.22 rows=199379 width=306) (actual time=229.866..229.968 rows=36 loops=1)
Filter: (article.magazine_id = 7)
Rows Removed by Filter: 116414
Je serais reconnaissant quelqu'un pourrait me donner des conseils pour mon plus débogage sur celui-ci.
Pourquoi la deuxième instruction devrait-elle utiliser l'arbre binaire si le résultat peut être complètement récupéré en utilisant l'index 'mmxxx_sitevideo_pkey' - avec une durée d'exécution de 0,2 millisecondes, cela me semble assez rapide. Le temps de planification a pris plus de temps que cela, mais le temps d'exécution total n'est toujours que de 1,5 ** milli ** secondes. Quelle performance attendez-vous? À quelle vitesse avez-vous besoin de cela? Bien que je dois admettre que les délais de planification (en particulier le premier) semblent assez élevés pour de telles déclarations simples. –
Oui ce que vous dites est tout à fait logique, mais je dois préciser que ceux-ci proviennent d'une configuration de développement avec beaucoup moins de données que le serveur de production. Sur le serveur de production, j'ai utilisé le module auto_explain et obtenu le même plan d'exécution. Dans mon développement DB j'ai seulement un magazine_id, sur le vrai serveur je reçois la même requête et puis cela prend plus de temps, désolé j'aurais dû ajouter la requête de production, l'ai maintenant ajouté au message original. (Vous avez également oublié de renommer cet index que vous mentionnez à idx_magazine_id pour "simplification" ;-)) – tdma
Ensuite, merci de poster le plan d'exécution (en utilisant 'explain (analyser, verbose)' depuis la production –