2017-09-02 19 views
1

je 1,3 milliard de lignes dans une table PostgreSQL sku_comparison qui ressemble à ceci:Comment mettre à jour 1,3 milliard de lignes dans ce tableau plus efficacement?

id1 (INTEGER) | id2 (INTEGER) | (10 SMALLINT columns) | length1 (SMALLINT)... | 

... length2 (SMALLINT) | length_difference (SMALLINT) 

Les id1 et id2 colonnes sont référencées dans un tableau appelé sku, qui contient environ 300 000 lignes, et ont une valeur varchar(25) associée à chaque rangée d'une colonne, code.

Il y a un indice de btree construit sur id1 et id2, et un indice composé de id1 et id2 dans sku_comparison. Il existe également un index btree sur la colonne id de sku.

Mon but est de mettre à jour les length1 et length2 colonnes avec les longueurs de la colonne code correspondante de la table sku. Cependant, j'ai couru le code suivant pour plus de 20 heures, et il n'a pas terminé la mise à jour:

UPDATE sku_comparison SET length1=length(sku.code) FROM sku 
WHERE sku_comparison.id1=sku.id; 

Toutes les données sont stockées sur un seul disque dur sur un ordinateur local, et le processeur est assez moderne. La construction de cette table, qui nécessitait des comparaisons de chaînes beaucoup plus compliquées en Python, ne prenait que 30 heures environ, donc je ne sais pas pourquoi quelque chose comme ça prendrait autant de temps.

modifier: définitions de table ici sont mises en forme:

         Table "public.sku" 
    Column |   Type   |     Modifiers      
------------+-----------------------+-------------------------------------------------- 
id   | integer    | not null default nextval('sku_id_seq'::regclass) 
sku  | character varying(25) | 
pattern | character varying(25) | 
pattern_an | character varying(25) | 
firsttwo | character(2)   | default ' '::bpchar 
reference | character varying(25) | 
Indexes: 
    "sku_pkey" PRIMARY KEY, btree (id) 
    "sku_sku_idx" UNIQUE, btree (sku) 
    "sku_firstwo_idx" btree (firsttwo) 
Referenced by: 
    TABLE "sku_comparison" CONSTRAINT "sku_comparison_id1_fkey" FOREIGN KEY (id1) REFERENCES sku(id) 
    TABLE "sku_comparison" CONSTRAINT "sku_comparison_id2_fkey" FOREIGN KEY (id2) REFERENCES sku(id) 


      Table "public.sku_comparison" 
      Column   | Type |  Modifiers   
---------------------------+----------+------------------------- 
id1      | integer | not null 
id2      | integer | not null 
consec_charmatch   | smallint | 
consec_groupmatch   | smallint | 
consec_fieldtypematch  | smallint | 
consec_groupmatch_an  | smallint | 
consec_fieldtypematch_an | smallint | 
general_charmatch   | smallint | 
general_groupmatch  | smallint | 
general_fieldtypematch | smallint | 
general_groupmatch_an  | smallint | 
general_fieldtypematch_an | smallint | 
length1     | smallint | default 0 
length2     | smallint | default 0 
length_difference   | smallint | default '-999'::integer 
Indexes: 
    "sku_comparison_pkey" PRIMARY KEY, btree (id1, id2) 
    "ssd_id1_idx" btree (id1) 
    "ssd_id2_idx" btree (id2) 
Foreign-key constraints: 
    "sku_comparison_id1_fkey" FOREIGN KEY (id1) REFERENCES sku(id) 
    "sku_comparison_id2_fkey" FOREIGN KEY (id2) REFERENCES sku(id) 
+0

Veuillez expliquer vos définitions de table en code (DDL), pas en texte. – wildplasser

+0

Votre mise à jour touchera * toutes * les lignes de 'sku_comparison_pkey'. Est-ce que les valeurs * changeront * pour toutes les lignes? – wildplasser

+0

Oui, toutes les valeurs sont mises à jour. J'ai utilisé psycopg2 de Python pour construire initialement la table par lots, mais avec le recul, j'ai oublié d'inclure les longueurs des codes, que je veux utiliser à côté des autres colonnes. –

Répondre

0

-vous envisager d'utiliser un bloc de code anonyme?

en utilisant le code pseudo ...

FOREACH 'SELECT ski.id, 
       sku.code, 
       length(sku.code) 
     FROM sku 
     INTO v_skuid, v_skucode, v_skulength' 
DO 
UPDATE sku_comparison 
SET sku_comparison.length1 = v_skulength 
WHERE sku_comparison.id1=v_skuid; 
END DO 
END FOREACH 

Cela romprait le tout en petites transactions et vous ne serez pas évaluerez la longueur de sku.code chaque fois.

+0

Que voulez-vous dire par "évaluer la longueur de sku.code à chaque fois"? –

+0

Aussi, je viens de me rappeler que mon insertion de données a été faite en parallèle avec 10 threads. Puis-je faire quelque chose de similaire avec des mises à jour si les lignes mises à jour ne se chevauchent pas? –

+0

@ user1362215, ce que je voulais dire par évaluer à chaque fois, c'est que votre sku_comparison a plusieurs instances du même sku.code et dans votre stmt de mise à jour, vous évaluiez la longueur à chaque ligne mise à jour. Mais si vous utilisez une boucle et que vous évaluez la longueur en dehors de la mise à jour stmt, vous ne gaspillerez pas les cycles du processeur sur l'évaluation de la longueur sur chaque ligne. –