J'ai une table Postgres avec environ 2,1 millions de lignes. J'ai exécuté la mise à jour ci-dessous:
WITH stops AS (
SELECT id,
rank() OVER (ORDER BY offense_timestamp,
defendant_dl,
offense_street_number,
offense_street_name) AS stop
FROM consistent.master
WHERE citing_jurisdiction=1
)
UPDATE consistent.master
SET arrest_id=stops.stop
FROM stops
WHERE master.id = stops.id;
Cette requête a pris 39 heures pour s'exécuter. J'exécute cela sur un processeur pour ordinateur portable i7 Q720 à 4 cœurs (physique), beaucoup de RAM, rien d'autre ne fonctionne la grande majorité du temps. Pas de contraintes d'espace disque dur. Le tableau avait récemment été aspiré, analysé et réindexé.
Pendant toute la durée de l'exécution de la requête, au moins après la fin de l'initialisation WITH
, l'utilisation du processeur était généralement faible et le disque dur était utilisé à 100%. Le disque dur était utilisé si durement que toute autre application fonctionnait beaucoup plus lentement que la normale.
Le paramètre d'alimentation de l'ordinateur portable était sur Haute performance (Windows 7 x64).
Voici l'EXPLIQUER:
Update on master (cost=822243.22..1021456.89 rows=2060910 width=312)
CTE stops
-> WindowAgg (cost=529826.95..581349.70 rows=2060910 width=33)
-> Sort (cost=529826.95..534979.23 rows=2060910 width=33)
Sort Key: consistent.master.offense_timestamp, consistent.master.defendant_dl, consistent.master.offense_street_number, consistent.master.offense_street_name
-> Seq Scan on master (cost=0.00..144630.06 rows=2060910 width=33)
Filter: (citing_jurisdiction = 1)
-> Hash Join (cost=240893.51..440107.19 rows=2060910 width=312)
Hash Cond: (stops.id = consistent.master.id)
-> CTE Scan on stops (cost=0.00..41218.20 rows=2060910 width=48)
-> Hash (cost=139413.45..139413.45 rows=2086645 width=268)
-> Seq Scan on master (cost=0.00..139413.45 rows=2086645 width=268)
citing_jurisdiction=1
exclut seulement quelques dizaines de milliers de lignes. Même avec cette WHERE
clause, j'opère toujours sur plus de 2 millions de lignes.
Le disque dur est entièrement chiffré avec TrueCrypt 7.1a. Que les choses de Ralentit un peu, mais pas assez pour causer une requête à prendre que de nombreuses heures.
La WITH
partie ne prend que 3 minutes environ pour fonctionner.
Le arrest_id
champ n'avait pas d'index pour la clé étrangère. Il y a 8 index et 2 clés étrangères sur cette table. Tous les autres champs de la requête sont indexés.
Le arrest_id
champ n'avait pas de contraintes sauf NOT NULL
.
Le tableau comprend 32 colonnes au total.
arrest_id
est de type variable (20) . Je me rends compte rank()
produit une valeur numérique, mais je dois utiliser la variation de caractère (20) parce que j'ai d'autres lignes où citing_jurisdiction<>1
qui utilisent des données non numériques pour ce champ.
Le arrest_id
champ était vide pour toutes les lignes avec citing_jurisdiction=1
.
Il s'agit d'un ordinateur portable personnel haut de gamme (il y a 1 an). Je suis le seul utilisateur. Aucune autre requête ou opération n'était en cours d'exécution. Le verrouillage semble peu probable.
Il n'y a aucun déclencheur nulle part dans cette table ou ailleurs dans la base de données.
Les autres opérations sur cette base de données ne prennent jamais un temps abornmal. Avec une indexation appropriée, les SELECT
requêtes sont généralement assez rapides.
Seq Scan
un peu effrayant ...