Question

J'ai exécuté une mise à jour sur une table contenant 250 millions de lignes avec 3 index '; Cette mise à jour utilise une autre table contenant 30 millions de lignes. Il fonctionne depuis environ 36 heures maintenant. Je me demande si leur est un moyen de savoir à quel point il est proche d'être fait pour si elle prévoit de prendre un million de jours pour faire son travail, je le tuerai; mais s'il ne lui faut qu'un jour ou deux, je le laisserai courir. Voici la commande-requête:

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0
;

La question EXPLAIN n’est pas le problème ici et je mentionne uniquement le fait que la grande table a plusieurs index afin de justifier en quelque sorte le temps qu’il faut pour la mettre à jour. Mais voici le EXPLAIN quand même:

Merge Join  (cost=127710692.21..135714045.43 rows=452882848 width=57)
  Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?"))
  ->  Sort  (cost=3193335.39..3219544.38 rows=10483593 width=41)
        Sort Key: page.page_namespace, (page.page_title)::text
        ->  Seq Scan on page  (cost=0.00..439678.01 rows=10483593 width=41)
              Filter: (page_is_redirect = 0::numeric)
  ->  Sort  (cost=124517356.82..125285665.74 rows=307323566 width=46)
        Sort Key: pagelinks.pl_namespace, (pagelinks.pl_title)::text"
        ->  Seq Scan on pagelinks  (cost=0.00..6169460.66 rows=307323566 width=46)

Maintenant, j’ai également envoyé une commande de requête parallèle afin de supprimer l’un des index de pagelinks '; Bien sûr, il attend la fin de la mise à jour (mais j'avais envie de l'essayer quand même!). Par conséquent, je ne peux rien sélectionner dans pagelinks par crainte de corrompre les données (à moins que vous ne pensiez qu'il serait prudent de supprimer le processus postmaster de DROP INDEX?).

Je me demande donc s’il s’agit d’un tableau qui tienne compte de la quantité de n-uplets morts ou de quelque chose comme ça. Il serait bien de savoir à quelle vitesse ou jusqu’à quel point la mise à jour est à jour dans sa tâche.

Thx (PostgreSQL n'est pas aussi intelligent que je le pensais; il a besoin d'heuristiques.)

Était-ce utile?

La solution

Avez-vous lu la documentation de PostgreSQL pour " Utilisation de EXPLAIN " ;, pour interpréter la sortie que vous affichez?

Je ne suis pas un utilisateur habituel de PostgreSQL, mais je viens de lire ce document, puis de le comparer à la sortie EXPLAIN que vous affichez. Votre requête UPDATE ne semble utiliser aucun index et est obligée d'effectuer des analyses de table pour trier les page et les pagelinks . Le tri est sans doute assez important pour nécessiter des fichiers de disque temporaires, créés à mon avis sous votre espace_table temporaire .

Ensuite, les pages de base de données estimées sont lues. Le niveau supérieur de cette sortie EXPLAIN dit (cost = 127710692.21..135714045.43) . Les unités ici sont dans les accès d'E / S de disque. Donc, il va accéder au disque plus de 135 millions de fois pour faire ceci UPDATE .

Notez que même des disques de 10 000 tr / min avec un temps de recherche de 5 ms peuvent réaliser au mieux 200 opérations d’E / S par seconde dans des conditions optimales. Cela signifie que votre UPDATE prendrait 188 heures (7,8 jours) d'E / S de disque, même si vous pouviez conserver des E / S de disque saturées pendant cette période (c'est-à-dire des lectures / écritures continues sans interruption). . C'est impossible, et je m'attendrais à ce que le débit réel soit réduit d'au moins un ordre de grandeur, d'autant plus que vous avez sans doute utilisé ce serveur pour toutes sortes d'autres tâches entre-temps. Je suppose donc que vous n'êtes plus qu'une fraction du chemin parcouru dans votre MISE À JOUR .

Si c’était moi, j’aurais tué cette requête le premier jour et trouver un autre moyen d’exécuter le UPDATE qui permettait de mieux utiliser les index et ne nécessitait pas de tri sur disque. Vous ne pouvez probablement pas le faire en une seule instruction SQL.

En ce qui concerne votre DROP INDEX , j'imagine qu'il bloque simplement l'attente d'un accès exclusif à la table et, même s'il se trouve dans cet état, vous pouvez probablement le supprimer.

Autres conseils

Ceci est très ancien, mais si vous voulez un moyen de surveiller votre mise à jour ... N'oubliez pas que les séquences sont affectées globalement, vous pouvez donc en créer une pour surveiller cette mise à jour dans une autre session en procédant comme suit:

create sequence yourprogress; 

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;

Dans une autre session, faites simplement ceci (ne vous inquiétez pas des transactions, car les séquences sont affectées globalement):

select last_value from yourprogress;

Ceci affichera le nombre de lignes affectées afin que vous puissiez estimer le temps que vous allez prendre.

À la fin de redémarrer votre séquence pour faire un autre essai:

alter sequence yourprogress restart with 1;

Ou simplement le laisser tomber:

drop sequence yourprogress;

Vous avez besoin d'index ou, comme Bill l'a souligné, il devra effectuer des analyses séquentielles sur toutes les tables.

CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top