2009-01-05 17 views
1

Je travaille actuellement avec une base de données PostgreSQL dérivée de wikipedia-dump plus grande; il contient environ 40 Go de données. La base de données fonctionne sur un serveur HP Proliant ML370 G5 avec Suse Linux Enterprise Server 10; Je l'interroge depuis mon ordinateur portable sur un réseau privé géré par un simple routeur D-Link. J'ai assigné des adresses IP statiques DHCP (privées) à l'ordinateur portable et au serveur.Optimisation de requêtes PosgreSQL et le processus Postmaster '

Quoi qu'il en soit, à partir de mon ordinateur portable, en utilisant pgAdmin III, j'envoie quelques commandes SQL/requêtes; certains d'entre eux sont CREATE INDEX, DROP INDEX, SUPPRIMER, SELECT, etc. Parfois, j'envoie une commande (comme CREATE INDEX), elle retourne, me disant que la requête a été exécutée parfaitement, etc. Cependant, le processus postmaster assigné à un tel La commande semble rester sur le serveur. Maintenant, cela ne me dérange pas vraiment, car je me dis que PostgreSQL maintient un pool de postmasters prêts à traiter les requêtes. Pourtant, si ce processus mange 6 Go de mémoire vive de 9,4 Go, je m'inquiète (et il le fait pour le moment). Maintenant, c'est peut-être un cache de données qui est conservé dans la mémoire [partagée] au cas où une autre requête aurait besoin d'utiliser ces mêmes données, mais je ne sais pas.

Une autre chose me dérange.

J'ai 2 tables. L'un est le tableau page; J'ai un index sur sa colonne page_id. L'autre est le pagelinks tables qui a la colonne de pl_from que les références soit rien ou une variable dans la page.page_id colonne; Contrairement à la colonne page_id, la pl_from n'a pas encore d'index. Pour vous donner une idée de l'échelle des tables et la nécessité pour moi de trouver une solution viable, page table a 13,4 millions de lignes (après avoir supprimé ceux dont je n'ai pas besoin) tandis que la table pagelinks a 293 millions.

J'ai besoin d'exécuter la commande suivante pour nettoyer les pagelinks tableau de certaines de ses lignes inutiles:

DELETE FROM pagelinks USING page WHERE pl_from NOT IN (page_id); 

Donc, fondamentalement, je veux débarrasser les pagelinks table de tous les liens provenant d'un page non dans la table page. Même après avoir désactivé les boucles imbriquées et/ou des analyses séquentielles, l'optimiseur de requêtes me donne toujours la « solution » suivante:

Nested Loop (cost=494640.60..112115531252189.59 rows=3953377028232000 width=6) 
    Join Filter: ("outer".pl_from <> "inner".page_id)" 
    -> Seq Scan on pagelinks (cost=0.00..5889791.00 rows=293392800 width=17) 
    -> Materialize (cost=494640.60..708341.51 rows=13474691 width=11) 
     -> Seq Scan on page (cost=0.00..402211.91 rows=13474691 width=11) 

Il semble que cette tâche prendrait plus de semaines pour compléter; évidemment, c'est inacceptable. Il me semble que je préfère utiliser l'index page_id pour faire son truc ... mais c'est un optimiseur têtu et je me trompe peut-être.

Une idée?

Répondre

1

En effet, je décide de créer une table temporaire pour accélérer l'exécution de la requête:

CREATE TABLE temp_to_delete AS(
    (SELECT DISTINCT pl_from FROM pagelinks) 
     EXCEPT 
    (SELECT page_id FROM page)); 
DELETE FROM pagelinks USING temp_to_delete 
    WHERE pagelinks.pl_from IN (temp_to_delete.pl_from); 

Étonnamment, cette requête terminée dans environ 4 heures alors que la requête initiale était resté actif pendant environ 14hrs avant que je décide de tuer il. Plus précisément, le SUPPRIMER retourné:

Query returned successfully: 31340904 rows affected, 4415166 ms execution time. 

En ce qui concerne la première partie de ma question, il semble que le processus de maître de poste conserve en effet quelques informations dans le cache; lorsqu'une autre requête nécessite des informations qui ne sont pas dans le cache et de la mémoire (RAM), le cache est vidé. Et les postmasters ne sont en effet qu'un pool de processus ».

Il m'est également venu à l'esprit que le gnome-system-monitor est un mythe car il donne des informations incomplètes et n'a aucune valeur informative. C'est principalement à cause de cette application que j'ai été si confus ces derniers temps; par exemple, il ne tient pas compte de l'utilisation de la mémoire des autres utilisateurs (comme l'utilisateur postgres!) et me dit même qu'il me reste 12 Go de RAM alors que c'est faux. Par conséquent, j'ai essayé quelques moniteurs de système car j'aime savoir comment postgreSQL utilise ses ressources, et il semble que xosview est en effet un outil valide.

Espérons que cela aide!

1

À votre deuxième question; vous pourriez essayer de créer une nouvelle table avec seulement les enregistrements dont vous avez besoin avec une instruction CREATE TABLE AS; Si la nouvelle table est suffisamment petite, elle pourrait être plus rapide, mais cela ne l'aidera peut-être pas non plus.

+0

En fait, c'est ce que je suis en train d'essayer car cela me semble être mon meilleur coup. Je posterai les résultats si cela fonctionne. THX! –

0

Votre processus postmaster restera là aussi longtemps que la connexion au client est ouverte. Est-ce que pgadmin ferme la connexion? Je ne sais pas.

La mémoire utilisée peut être shared_buffers (vérifiez vos paramètres de configuration) ou non.

Maintenant, la requête. Pour les grosses opérations de maintenance comme celle-ci, n'hésitez pas à définir work_mem sur quelque chose de gros comme quelques Go. Vous avez l'air d'avoir beaucoup de RAM, alors utilisez-le.

définissez work_mem sur '4GB'; EXPLAIN SUPPRIMER DE pagelinks OERE pl_from NOT IN (SELECT page_id FROM page);

Il devrait analyser la page, hacher et analyser les pagelinks, jetant un coup d'œil dans le hachage pour vérifier la présence de page_ids. Cela devrait être assez rapide (beaucoup plus rapide que 4 heures!) Mais vous avez besoin d'un gros work_mem pour le hash.

Mais puisque vous supprimez une partie importante de votre table, il peut être plus rapide de le faire comme ceci:

CREATE TABLE pagelinks2 AS SELECT * FROM un pagelinks JOIN pages BMARCHE a.pl_from = b.. page_id;

(vous pouvez utiliser un simple REJOIGNEZ au lieu de)

Vous pouvez également ajouter une clause ORDER BY sur cette requête, et votre nouvelle table sera bien ordonnée sur le disque pour un accès optimal plus tard.