PostgreSQL - Pour vous qui voulez INSÉRER à grande vitesse

Améliorons les performances des inserts de masse

Pour les insertions en masse dans PostgresQL Utilisez l'utilitaire pour insérer plusieurs enregistrements ensemble. Vous pouvez également revoir la fréquence d'exécution des validations pour réduire les coûts de traitement inutiles.

Mesurez en fait avec plusieurs modèles et comparez les performances. Dans psycopg2, l'une des bibliothèques qui accèdent à PostgreSQL avec Python En tant qu'utilitaire pour insérer plusieurs éléments à la fois Utilisez une fonction appelée execute_values. Modifiez également l'unité d'exécution de la validation et modifiez l'intervalle d'exécution de la validation pour la mesure réelle.

Préparation à la confirmation

Table de test

Tester DDL


CREATE TABLE test01
(key serial PRIMARY KEY,
 text_val text);

Programme de test

Pour plus de simplicité, nous allons vous permettre de saisir le nombre d'exécutions et de commits de manière interactive. Incluez la partie qui crée les paramètres afin qu'ils puissent être comparés autant que possible dans la même plage de temps. Initialisez les valeurs des objets TRUNCATE et SEQUENCE pour réinitialiser la table à chaque fois avant l'exécution.

execute_values prend par défaut 100 lignes. Si vous entrez plus que cela, vous devez passer plus que le nombre d'entrées à l'argument taille_page.

Programme de test


import psycopg2
from psycopg2.extras import execute_values
from time import time

_text = 'test' * 300

conn = psycopg2.connect('dbname=dbname host=localhost user=username password=password')
cur = conn.cursor()

#Réinitialisation de la table
reset_query_tbl = "TRUNCATE TABLE test01;"
cur.execute(reset_query_tbl)
reset_query_seq = "SELECT setval ('test01_key_seq', 1, false);"
cur.execute(reset_query_seq)
count_query = "SELECT count(key) FROM test01;"
cur.execute(count_query)
(count,) = cur.fetchone()
conn.commit()
print('■ État avant exécution')
print('Nombre de données: ', count)
print()

#Paramètres de test
print('■ Méthode INSERT')
print('Veuillez sélectionner la méthode INSERT parmi les suivantes(0/1/2/3)')
print(' 0:INSÉRER un par un&commit.')
print(' 1:INSÉRER un par un&Engagement collectif multiple.')
print(' 2:INSÉRER un par un&Tous les cas s'engagent collectivement.')
print(' 3:INSÉRER collectivement&commit.')
test_type = int(input('INSERT, méthode>'))
test_cnt  = int(input('Nombre d'INSERTs>'))
if test_type == 1:
    commit_cnt  = int(input('Intervalle COMMIT>'))

#Exécution du test et résultat
print()
print('■ Résultat de l'exécution')
if test_type==0:

    query = "INSERT INTO test01 (text_val) VALUES ('%s');" % _text
    st = time()
    for _ in range(test_cnt):
        cur.execute(query)
        conn.commit()

    elapsed_time = time() - st
    print('temps écoulé(s): ', elapsed_time)

if test_type==1:
    query = "INSERT INTO test01 (text_val) VALUES ('%s');" % _text
    st = time()
    for i in range(test_cnt):
        cur.execute(query)
        if (i + 1) % commit_cnt == 0:
            conn.commit()

    conn.commit()

    elapsed_time = time() - st
    print('temps écoulé(s): ', elapsed_time)

if test_type==2:

    query = "INSERT INTO test01 (text_val) VALUES ('%s');" % _text
    st = time()
    for _ in range(test_cnt):
        cur.execute(query)

    conn.commit()

    elapsed_time = time() - st
    print('temps écoulé(s): ', elapsed_time)

if test_type==3:

    query = "INSERT INTO test01 (text_val) VALUES %s;"
    st = time()

    params = []
    for _ in range(test_cnt):
        params += [(_text,)]

    ret = execute_values(cur, query, params, page_size=test_cnt)
    conn.commit()
    elapsed_time = time() - st
    print('temps écoulé(s): ', elapsed_time)

cur.execute(count_query)
(count,) = cur.fetchone()
print('Nombre de données: ', count)

cur.close()
conn.close()

Résultats de performance

Les résultats sont à titre indicatif seulement. Bien entendu, cela dépend de l'environnement et des spécifications de la machine.

--Windows10 64 bits / nombre de processeurs logiques 4 / mémoire 8 Go

INSERT, méthode Nombre d'INSERTs COMMIT count temps de traitement(S)
INSÉRER un par un(execute) &S'ENGAGER un par un. 100,000 100,000 40.9
INSÉRER un par un(execute) &10 ENGAGEMENTS chacun. 100,000 10,000 25.4
INSÉRER un par un(execute) &100 chaque COMMIT. 100,000 1,000 24.1
INSÉRER un par un(execute) & 1,000 ENGAGEMENT. 100,000 100 27.2
INSÉRER un par un(execute) & 10,COMMIT par 000. 100,000 10 25.9
INSÉRER un par un(execute) &Tous les cas s'engagent collectivement. 100,000 1 24.4
INSÉRER collectivement(execute_values) &Tous les cas s'engagent collectivement. 100,000 1 8.8

Conclusion

execute_values, rapide. Utilisez-le si vous le pouvez.

Recommended Posts

PostgreSQL - Pour vous qui voulez INSÉRER à grande vitesse
Comment créer des fichiers volumineux à haute vitesse
Points ennuyeux pour ceux qui veulent présenter Ansible
Pour ceux qui veulent écrire Python avec vim
Pour ceux qui souhaitent démarrer l'apprentissage automatique avec TensorFlow2
Référence de référence pour ceux qui veulent coder avec Rhinoceros / Grasshopper
Procédure d'inscription PyPI pour ceux qui veulent faire leurs débuts PyPI
[Python] Comment obtenir la fraction d'un nombre naturel à grande vitesse
Articles en vrac pour ceux qui veulent commencer le traitement du langage naturel
Technique Python pour ceux qui veulent se débarrasser des débutants
J'ai analysé les données Airbnb pour ceux qui veulent rester à Amsterdam
Rejoignez Azure avec Go ~ Pour ceux qui veulent démarrer et connaître Azure avec Go ~
Pour ceux qui veulent apprendre Excel VBA et se lancer avec Python
5 raisons pour lesquelles le traitement est utile pour ceux qui veulent se lancer avec Python
[Flask + Keras] Comment déduire plusieurs modèles à grande vitesse sur le serveur
Je veux INSÉRER un DataFrame dans MSSQL
La première étape de l'apprentissage automatique ~ Pour ceux qui veulent essayer l'implémentation avec python ~
Construction d'environnement pour ceux qui veulent étudier Python facilement avec VSCode (pour Mac)