Question

Je vais essayer d'obtenir les postgres texte intégral-moteur de recherche fonctionnelle.

J'ai deux tables, un que j'ai créé juste pour le test, et le réel, je veux être en mesure de rechercher:

Table De Test:

webarchive=# \d test_sites
                            Table "public.test_sites"
   Column    |   Type   |                        Modifiers
-------------+----------+---------------------------------------------------------
 id          | integer  | not null default nextval('test_sites_id_seq'::regclass)
 content     | text     |
 tsv_content | tsvector |
Indexes:
    "test_sites_pkey" PRIMARY KEY, btree (id)
    "idx_test_web_pages_content" gin (tsv_content)
Triggers:
    web_pages_testing_content_change_trigger AFTER INSERT OR UPDATE ON test_sites FOR EACH ROW EXECUTE PROCEDURE web_pages_testing_content_update_func()

"Réel" De La Table:

webarchive=# \d web_pages
                                      Table "public.web_pages"
    Column    |            Type             |                       Modifiers
--------------+-----------------------------+--------------------------------------------------------
 id           | integer                     | not null default nextval('web_pages_id_seq'::regclass)
 state        | dlstate_enum                | not null
 errno        | integer                     |
 url          | text                        | not null
 starturl     | text                        | not null
 netloc       | text                        | not null
 file         | integer                     |
 priority     | integer                     | not null
 distance     | integer                     | not null
 is_text      | boolean                     |
 limit_netloc | boolean                     |
 title        | citext                      |
 mimetype     | text                        |
 type         | itemtype_enum               |
 raw_content  | text                        |
 content      | text                        |
 fetchtime    | timestamp without time zone |
 addtime      | timestamp without time zone |
 tsv_content  | tsvector                    |
Indexes:
    "web_pages_pkey" PRIMARY KEY, btree (id)
    "ix_web_pages_url" UNIQUE, btree (url)
    "idx_web_pages_content" gin (tsv_content)
    "idx_web_pages_title" gin (to_tsvector('english'::regconfig, title::text))
    "ix_web_pages_distance" btree (distance)
    "ix_web_pages_distance_filtered" btree (priority) WHERE state = 'new'::dlstate_enum AND distance < 1000000
    "ix_web_pages_priority" btree (priority)
    "ix_web_pages_type" btree (type)
    "ix_web_pages_url_ops" btree (url text_pattern_ops)
Foreign-key constraints:
    "web_pages_file_fkey" FOREIGN KEY (file) REFERENCES web_files(id)
Triggers:
    web_pages_content_change_trigger AFTER INSERT OR UPDATE ON web_pages FOR EACH ROW EXECUTE PROCEDURE web_pages_content_update_func()

Des bits supplémentaires de côté, les deux ont un content la colonne, et un tsv_content colonne avec un gin() index sur elle.Il est un déclencheur qui met à jour le tsv_content colonne à chaque fois que l' content la colonne est modifié.

Notez que l' d'autres gin index fonctionne très bien, et j'ai d'abord eu un gin (to_tsvector('english'::regconfig, content::text)) indice sur le contenu de la colonne ainsi, au lieu de la deuxième colonne, mais après une attente pour que l'indice de reconstruire un peu de temps pour les tests, j'ai décidé d'utiliser une colonne séparée pour pré-stocker les tsvector valeurs.

Exécution d'une requête sur la table de test utilise l'index, comme je l'espère:

webarchive=# EXPLAIN ANALYZE SELECT
    test_sites.id,
    test_sites.content,
    ts_rank_cd(test_sites.tsv_content, to_tsquery($$testing$$)) AS ts_rank_cd_1
FROM
    test_sites
WHERE
    test_sites.tsv_content @@ to_tsquery($$testing$$);
                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test_sites  (cost=16.45..114.96 rows=25 width=669) (actual time=0.175..3.720 rows=143 loops=1)
   Recheck Cond: (tsv_content @@ to_tsquery('testing'::text))
   Heap Blocks: exact=117
   ->  Bitmap Index Scan on idx_test_web_pages_content  (cost=0.00..16.44 rows=25 width=0) (actual time=0.109..0.109 rows=143 loops=1)
         Index Cond: (tsv_content @@ to_tsquery('testing'::text))
 Planning time: 0.414 ms
 Execution time: 3.800 ms
(7 rows)

Cependant, l' exactement la même requête sur la table réelle ne semble jamais de résultat dans quoi que ce soit mais un simple vieux analyse séquentielle:

webarchive=# EXPLAIN ANALYZE SELECT
       web_pages.id,
       web_pages.content,
       ts_rank_cd(web_pages.tsv_content, to_tsquery($$testing$$)) AS ts_rank_cd_1
   FROM
       web_pages
   WHERE
       web_pages.tsv_content @@ to_tsquery($$testing$$);
                                                       QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
 Seq Scan on web_pages  (cost=0.00..4406819.80 rows=19751 width=505) (actual time=0.343..142325.954 rows=134949 loops=1)
   Filter: (tsv_content @@ to_tsquery('testing'::text))
   Rows Removed by Filter: 12764373
 Planning time: 0.436 ms
 Execution time: 142341.489 ms
(5 rows)

J'ai augmenté mon travail de mémoire de 3 GO pour voir si c'était la question, et il ne l'est pas.

En outre, il convient de noter que ces sont assez grandes tables - ~150 GO de texte sur 4M de lignes (avec 8M de lignes supplémentaires où content/tsv_content est NULL).

L' test_sites tableau a 1/1000e de la lignes de web_pages, comme il est un peu prohibitif essayer lors de chaque requête prend plusieurs minutes.


Je suis en utilisant postgresql 9.5 (oui, j'ai compilé moi-même, je voulais ON CONFLICT).Il ne semble pas être une balise pour que encore.

J'ai lu attentivement la questions ouvertes avec 9.5, et je ne peux pas voir ce qui est un résultat de l'un d'eux.


Frais d'une reconstruction complète de l'index, le problème existe toujours:

webarchive=# ANALYZE web_pages ;
ANALYZE
webarchive=# EXPLAIN ANALYZE SELECT
    web_pages.id,
    web_pages.content,
    ts_rank_cd(web_pages.tsv_content, to_tsquery($$testing$$)) AS ts_rank_cd_1
FROM
    web_pages
WHERE
    web_pages.tsv_content @@ to_tsquery($$testing$$);
                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on web_pages  (cost=10000000000.00..10005252343.30 rows=25109 width=561) (actual time=7.114..146444.168 rows=134949 loops=1)
   Filter: (tsv_content @@ to_tsquery('testing'::text))
   Rows Removed by Filter: 13137318
 Planning time: 0.521 ms
 Execution time: 146465.188 ms
(5 rows)

Notez que j'ai littéralement juste ANALYZEed, et seqscan est désactivé.

Était-ce utile?

La solution

Eh bien, j'ai passé un peu de temps à faire un peu d'espace supplémentaire sur le disque avec la DB sur elle, le déplacement de certaines autres bases de données à un autre SSD.

J'ai ensuite couru VACUUM ANALYZE à travers l'ensemble de la base de données, et maintenant, apparemment, il a remarqué que j'ai l'index.

J'avais déjà les deux analysées et l'aspirateur juste ce tableau, mais apparemment , c'est en quelque sorte fait une différence pour le faire, en général, plutôt qu'à une table spécifique.Aller à la figure.

webarchive=# EXPLAIN ANALYZE SELECT
    web_pages.id,
    web_pages.content
FROM
    web_pages
WHERE
    web_pages.tsv_content @@ to_tsquery($$testing$$);
                                                                 QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on web_pages  (cost=1185.79..93687.30 rows=23941 width=189) (actual time=41.448..152.108 rows=134949 loops=1)
   Recheck Cond: (tsv_content @@ to_tsquery('testing'::text))
   Heap Blocks: exact=105166
   ->  Bitmap Index Scan on idx_web_pages_content  (cost=0.00..1179.81 rows=23941 width=0) (actual time=24.940..24.940 rows=134996 loops=1)
         Index Cond: (tsv_content @@ to_tsquery('testing'::text))
 Planning time: 0.452 ms
 Execution time: 154.942 ms
(7 rows)

J'ai également profité de l'occasion pour lancer un VACUUM FULL; maintenant que j'ai assez d'espace pour le traitement.J'ai eu un peu juste de la ligne-le taux de désabonnement, dans le tableau que j'ai fait l'expérience au cours du développement et j'aimerais essayer de consolider toute la fragmentation des fichiers qui en a résulté que.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top