मेरे पास IP पते का 5GB CSV है जिसे मुझे एक MySQL डेटाबेस में पार्स करने की आवश्यकता है।

वर्तमान में CSV से पंक्तियों को पढ़ना और MySQL में सम्मिलित करना। यह बहुत अच्छा काम करता है हालांकि मैं इसे तेजी से बनाना पसंद करूंगा।

क्या मैं किसी तरह पढ़ने और लिखने को समानांतर कर सकता हूँ? या शायद प्रत्येक विभाजन सीएसवी को पढ़ने और लिखने के लिए सीएसवी को नीचे दबाएं और प्रक्रियाओं से स्पॉन करें?

import csv
from csv import reader
from csv import writer
import mysql.connector

cnx = mysql.connector.connect(user='root', password='', host='127.0.0.1', database='ips')
cursor = cnx.cursor()
i = 1

with open('iplist.csv', 'r') as read_obj:
    csv_reader = reader(read_obj)
    for row in csv_reader:
        query = """INSERT INTO ips (ip_start,ip_end,continent) VALUES ('%s','%s','%s')""" % (row[0],row[1],row[2])
        print (query)
        cursor.execute(query)
        cursor.execute('COMMIT')
        print(i)
        i = i + 1
cnx.close()

किसी भी मदद की सराहना की जाती है।

0
Martin 7 सितंबर 2021, 08:44

2 जवाब

सबसे बढ़िया उत्तर

मैंने एक छद्म-यादृच्छिक सीएसवी फ़ाइल बनाई जहां प्रत्येक पंक्ति "111.222.333.444,555.666.777.888, एक महाद्वीप" शैली की है। फ़ाइल में 33 मिलियन पंक्तियाँ हैं। निम्नलिखित कोड ~3 मिनट में सभी पंक्तियों को एक MySQL डेटाबेस तालिका में सम्मिलित करने में सक्षम था: -

import mysql.connector
import time
import concurrent.futures
import csv
import itertools

CSVFILE='/Users/Andy/iplist.csv'
CHUNK=10_000


def doBulkInsert(rows):
    with mysql.connector.connect(user='andy', password='monster', host='localhost', database='andy') as connection:
        connection.cursor().executemany(f'INSERT INTO ips (ip_start, ip_end, continent) VALUES (%s, %s, %s)', rows)
        connection.commit()


def main():
    _s = time.perf_counter()
    with open(CSVFILE) as csvfile:
        csvdata = csv.reader(csvfile)
        _s = time.perf_counter()
        with concurrent.futures.ThreadPoolExecutor() as executor:
            while (data := list(itertools.islice(csvdata, CHUNK))):
                executor.submit(doBulkInsert, data)
            executor.shutdown(wait=True)
            print(f'Duration = {time.perf_counter()-_s}')    

if __name__ == '__main__':
    main()
1
DarkKnight 7 सितंबर 2021, 13:14

गति बढ़ाने के लिए cursor.executemany का प्रयोग करें:

# Tested with:
# docker run --rm -e MYSQL_ALLOW_EMPTY_PASSWORD=y -p 3306:3306 mysql
#
# CREATE DATABASE ips;
# USE ips;
# CREATE TABLE ips (id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, ip_start VARCHAR(15), ip_end VARCHAR(15), continent VARCHAR(20));

import mysql.connector
import csv
import itertools

CHUNKSIZE = 1000  # Number of lines

cnx = mysql.connector.connect(user='root', password='', host='127.0.0.1', database='ips')
cursor = cnx.cursor()

with open('iplist.csv', 'r') as csvfile:
    reader = csv.reader(csvfile)
    while True:
        records = list(itertools.islice(reader, CHUNKSIZE))
        if not records:
            break
        query = """INSERT INTO ips (ip_start, ip_end, continent) VALUES (%s, %s, %s)"""
        cursor.executemany(query, records)
        cursor.execute('COMMIT')
2
Corralien 7 सितंबर 2021, 10:37