1
resposta

Bulk Insert em lotes via Python

Estou com problemas em dividir o values do bulk-insert pois a ideia e realizar 1 insert a cada 10 values por vez e lendo todo o conteudo do arquivo csv

O codigo ja faz o insert em um unica linha lendo todo o arquivo csv porem não estou conseguindo realizar a divisão dos VALUES para no caso futuramente realizar uma insert de 10 mil values por vez.

def bulk_insert(table_name, **kwargs):

    mysqlConnection = MySqlHook(mysql_conn_id='id_db')
    a = mysqlConnection.get_conn()
    c = a.cursor()

    with open('/pasta/arquivo.csv') as f: 
        reader = csv.reader(f, delimiter='\t')

        sql ="""INSERT INTO user (id,user_name) VALUES""" 

            for row in reader:           
                sql +="(" + row[0] + " , '" + row[1] + "'),"
            c.execute(sql[:-1])  

    a.commit()
1 resposta

Oiii André, tudo bem com você?

Para realizar 1 insert a cada 10 values por vez você pode utilizar o enumerate para ver em qual index a lista de reader está e a cada 10 values você executa aquele insert. O for ficaria similar ao código abaixo. Simulei as execuções com um print, mas também funciona com o banco:

def executa():
    print("Executa o sql")


def bulk_insert():
    reader = [
        'Andy', 'Smith', 'Fidy', 'Williams', 'John', 'Johnson', 'Patrick', 'Keating', 'Cristina', 'Abranhan',
        'Michel', 'Otávio', 'Augusto', 'Fernando', 'Fábio', 'José', 'Maria', 'Geovani', 'Noronha', 'Cássio',
        'Fabiola', 'Hashid', 'Erick', 'Vinícius', 'Halford', 'Kara', 'Lopes', 'Oliveira', 'Bernard', 'Anny',
        'Cierra', 'Vega', 'Alden', 'Cantrell', 'Kierra', 'Gentry', 'Pierre', 'Cox', 'Thomas', 'Crane',
        'Miranda', 'Shaffer', 'Bradyn', 'Kramer', 'Alvaro', 'Mcgee', 'Cindy', 'Clements', 'Carissa', 'Arias',
        'Spencer', 'Woodward', 'Kareem', 'Mitchell', 'Shawn', 'Benitez']
    sql = """INSERT INTO user (id,user_name) VALUES"""

    for index, row in enumerate(reader):
        sql += "(" + row[0] + " , '" + row[1] + "'),"
        if (index+1) % 10 == 0 and index != 0:
            print(sql[:-1])
            executa()
            sql = """INSERT INTO user (id,user_name) VALUES"""


bulk_insert()

Contudo, vale ressaltar o uso do executemany para inserções em massa, pois o mesmo recebe uma sequência de parâmetros e irá executar a query nesses parâmetros . Por exemplo:

data = [
  ('Jane', date(2005, 2, 12)),
  ('Joe', date(2006, 5, 23)),
  ('John', date(2010, 10, 3)),
]
stmt = "INSERT INTO employees (first_name, hire_date) VALUES (%s, %s)"
cursor.executemany(stmt, data)

Internamente o mysql irá interpretar a instrução acima da seguinte maneira:

INSERT INTO employees (first_name, hire_date)
VALUES ('Jane', '2005-02-12'), ('Joe', '2006-05-23'), ('John', '2010-10-03')

Então, a depender da forma como seus dados estão organizados poderá utilizar o executemany fazendo slices nos dados de 10 em 10:

cursor.executemany(sql, reader[:10])
cursor.executemany(sql, reader[10:20])

Qualquer dúvida é só falar. Abraços e bons estudos!