2013-04-08 4 views
1

J'utilise une base de données pour représenter une liste de fichiers et certaines métadonnées associées à chacun d'entre eux. J'ai besoin de mettre à jour régulièrement cette liste de fichiers, en ajoutant seulement les nouveaux fichiers et en supprimant les fichiers qui n'existent plus (je ne dois pas toucher les lignes existantes dans le tableau car je perdrais les métadonnées associées).Insertion incrémentielle efficace dans postgresql

Mes requêtes actuelles ne prennent que quelques secondes lorsque j'ai environ 10000 fichiers, mais prennent une heure avec ma table actuelle de 150000 fichiers.

Après quelques recherches sur Internet, je suis le processus suivant:

  1. Peupler une table "NewFiles" avec les résultats de l'analyse
  2. DELETE FROM files WHERE path NOT IN (SELECT path FROM newfiles);
  3. INSERT INTO files (SELECT * FROM newfiles WHERE path NOT IN (SELECT path FROM files));

J'ai aussi des index:

CREATE INDEX "files_path" ON "files" ("path"); 
CREATE INDEX "files_path_like" ON "files" ("path" varchar_pattern_ops); 
CREATE INDEX "files_path" ON "newfiles" ("path"); 
CREATE INDEX "files_path_like" ON "newfiles" ("path" varchar_pattern_ops); 

(J'utilise principalement ces index pour la recherche dans la base de données; mon application a un moteur de recherche dans les fichiers.)

Chacune de ces deux requêtes prend plus d'une heure quand j'ai 150000 fichiers. Comment puis-je optimiser cela?

Merci.

+0

Une option parfois viable consiste à ajouter de nouvelles partitions: créer une nouvelle table qui 'INHERITS' une table parente, ajouter une contrainte appropriée, la peupler, créer des index sur elle. Cela ne fonctionne que lorsque vos nouvelles données peuvent être clairement partitionnées sur une seule contrainte. –

+0

Cela ressemble plus à un problème d'ES de mémoire ou de disque. 150K lignes n'est pas un montant énorme - peut-être vous avez juste besoin d'allouer plus de mémoire à postgres? Même alors, quelle est la taille de la table. Il ne devrait pas prendre une heure pour lire toutes ces données à partir du disque. – AngerClown

Répondre

1

Essayez NOT EXISTS au lieu de NOT IN, comme dans:

DELETE FROM files WHERE NOT EXISTS 
    (SELECT 1 FROM newfiles WHERE newfiles.path=files.path); 

Aussi, si newfiles est peuplée chaque fois à partir de zéro, assurez-vous que vous ANALYZE newfiles avant d'émettre une requête qui utilise, de sorte que l'optimiseur peut fonctionner avec bonnes statistiques.

Si cela ne résout pas, essayez EXPLAIN ou EXPLAIN ANALYZE sur vos requêtes pour avoir le plan d'exécution et l'ajouter à la question.

+0

Désolé d'avoir complètement oublié j'ai demandé à ce sujet ici ... -_- – alphatiger

+0

Cela a beaucoup aidé, en fait maintenant, il prend moins d'une seconde pour chaque requête. Après avoir essayé les deux options, il utilise 'NOT EXISTS' au lieu de' NOT IN' qui a aidé. Merci beaucoup! – alphatiger

Questions connexes