7
votes

Déposer et créer vs Supprimer et insérer dans PostgreSQL

Je dois dupliquer des valeurs d'une table à une autre (schémas de table identiques). Quoi de mieux (performance):

  • Drop Table1 et créez comme SELECT * de TABLE2
  • Supprimez toutes les lignes de la table1 et insérez toutes les lignes de TABLE2

    mise à jour: J'ai fait un petit test sur la table avec presque 3k rangées. Drop and Create donne environ 60 ms vs Supprimer et insérer - environ 30 ms.


3 commentaires

Mon intuition me dit que le moyen le plus rapide serait tronquer et insérer, car Supprimera toutes les rangées et les supprime individuellement, alors que le tronquage tout simplement vide la table sans conditions possibles.


3k rangées .... Sérieusement? .... et vous parlez de performance? ... Optimisation prématurée Toute personne? Lorsque j'ai lu votre message initial, je pensais que vous parliez de plusieurs millions de rangées. 3k rangées est rien . Pour les rangées de 3k, vous n'avez probablement même pas besoin d'une DB;)


Cela dépend de la fréquence à laquelle il a besoin de le faire et à quelle fréquence les transactions simultanées doivent-elles y accéder, n'est-ce pas? :)


4 Réponses :


1
votes

Si vous parlez de l'exécution du Insérer s manuellement, un par un, puis goutte / Créer sera beaucoup plus rapide. En outre, lorsque vous utilisez Créer une table comme , il ne sera que copier les définitions de la colonne. Les indices et d'autres contraintes seront pas être copiés. Cela accélérera le processus de copie énormément . Mais vous devrez vous rappeler de les ré-créer sur la nouvelle copie une fois que vous avez terminé.

Il en va de même pour Sélectionnez dans . Ils sont fonctionnellement identiques. Ils ont juste des noms différents.

Dans tous les cas. Lors de la copie de grandes tables, désactivez toujours les déclencheurs, les indices et les contraintes pour gagner des performances.


0 commentaires

2
votes

Utilisez tronquée au lieu de la table de goutte ou supprimez lorsque vous devez vous débarrasser de tous les enregistrements d'une table. Avec tronquage, vous pouvez toujours utiliser des déclencheurs dans PostgreSQL et les autorisations sont plus faciles à définir et à entretenir.

Comme une goutte, TronCate a également besoin d'une serrure de table.


0 commentaires

17
votes

Je vois quatre moyens utiles de remplacer le contenu de la table. Aucun d'entre eux n'est "évidemment juste", mais cela dépend de vos besoins.

  1. (dans une seule transaction) Supprimer de FOO; Insérer dans FOO SELECT ... CODE> P>

    pro: strong> Meilleur concurrence: ne verrouille pas d'autres transactions Accès à la table, car elle exploite le MVCC de Postgres. P>

    con: strong> probablement le plus lent si vous mesurez la vitesse d'insertion seule. Cause Autovacuum pour nettoyer les lignes mortes, créant ainsi une charge d'E / S plus élevée. P> li>

  2. tronqua foo; Insérer dans FOO SELECT ... CODE> P>

    pro: strong> le plus rapide pour les tables plus petites. Causes moins d'écriture I / O que n ° 1 p>

    con: strong> exclut tous les autres lecteurs - autres transactions La lecture de la table devra attendre. p> li>

  3. tronquez FOO code>, déposez tous les index sur table, Insérer dans FOO SELECT ... CODE>, recréez tous les index. P>

    pro: strong> le plus rapide pour les grandes tables, car la création d'index avec Créer Index code> est plus rapide que la mise à jour progressivement. P>

    con: strong> même que # 2 p> li>

  4. le commutateur. Créez deux tables identiques FOO CODE> et FOO_TMP CODE> P>

    TRUNCATE foo_tmp;
    INSERT INTO foo_tmp SELECT ...;
    ALTER TABLE foo RENAME TO foo_tmp1;
    ALTER TABLE foo_tmp RENAME TO foo;
    ALTER TABLE foo_tmp1 RENAME TO foo_tmp;
    


3 commentaires

Je devais renommer / déposer mes index après avoir fait le numéro 4 et le n ° 3 combiné. Les index primaires-clés sont renommés automatiquement, d'autres ne le sont pas. Le temps total pour déposer et reconstruire ~ 800.000 rangs d'une vue allait de 90 à environ 20 ans. Merci pour le conseil.


Cette réponse contient-elle toujours avec les dernières versions de PostgreSQL comme 10+?


@PirateApp Il y a une méthode supplémentaire pour faire cela en utilisant Insert ... sur la mise à jour des conflits, etc., avec ses propres compromis. En dehors de cela, il y a eu des optimisations plus petites, mais ce que j'ai écrit est toujours pertinent.



0
votes

Voici les horaires (comparatifs) pour la réponse de Intgr (voir le code ci-dessous):

  1. Supprimer / insert - 36 sec. Li>
  2. tronquage / insert - 19 sec. li>
  3. index de goutte / tronquage / insert / créer index - 13 sec. p>

    -- preparations
    drop table if exists temp_refresh_experiment;
    -- million random strings
    create table temp_refresh_experiment as
    select 
        upper(substr(md5(random()::text), 0, 25)) as some_column
    FROM
        generate_series(1,1000000) i;
    -- create index
    create index temp_refresh_experiment_ix on temp_refresh_experiment(some_column)
    ;
    
    
    -- 1. delete/insert
    delete from temp_refresh_experiment;
    insert into temp_refresh_experiment(some_column)
    select
    upper(substr(md5(random()::text), 0, 25)) as some_column
    FROM
        generate_series(1,1000000) i;
    -- 36 secs
    
    
    -- 2. truncate/insert
    truncate temp_refresh_experiment;
    insert into temp_refresh_experiment(some_column)
    select
    upper(substr(md5(random()::text), 0, 25)) as some_column
    FROM
        generate_series(1,1000000) i;
    -- 19 sec   
    
    
    -- 3. drop index/truncate/insert/create index
    drop index if exists temp_refresh_experiment_ix;
    truncate temp_refresh_experiment;
    insert into temp_refresh_experiment(some_column)
    select
    upper(substr(md5(random()::text), 0, 25)) as some_column
    FROM
        generate_series(1,1000000) i; 
    create index temp_refresh_experiment_ix on temp_refresh_experiment(some_column)
    ;
    -- 13 sec
    


0 commentaires