Разбор большого файла csv в tinydb занимает вечность

У меня есть большой CSV-файл, содержащий 15 столбцов и примерно 1 миллион строк. Я хочу разобрать данные в tinyDB. Код, который я использую, приведен ниже:

import csv
from tinydb import TinyDB

db = TinyDB('db.monitor')
table = db.table('Current')

i=0

datafile = open('newData.csv', 'rb')
data=csv.reader(datafile, delimiter = ';')

for row in data:
    table.insert({'WT_ID': row[0], 'time': row[1], 'MeanCurrent': row[2], 'VapourPressure': row[3], 'MeanVoltage':row[4], 'Temperature': row[5], 'Humidity': row[6], 'BarPressure': row[7], 'RPM': row[8], 'WindSector': row[9], 'WindSpeed': row[10], 'AirDensity': row[12], 'VoltageDC': row[13], 'PowerSec': row[14], 'FurlingAngle': row[15]})
    i=i+1
    print i

Однако на самом деле это занимает вечность. Я установил переменную i для отслеживания прогресса, и если в первых строках он работает быстро, то сейчас прошло больше часа, и он проанализировал около 10000 строк в темпе почти 1 Гц.

Я не мог найти ничего подобного, поэтому любая помощь будет оценена по достоинству.

Спасибо


person tzoukritzou    schedule 23.12.2016    source источник
comment
это, вероятно, следует переместить на codereview.stackexchange.com - и, возможно, вам следует проверить insert_multiple()   -  person Mike Scotty    schedule 23.12.2016
comment
У меня была та же проблема, что вставки стали очень медленными (например, 1/сек) после 300 вставок. Установка ujson и использование insert_multiple ускорили мою вставку на порядки. Точно не измерено, но примерно от 50 секунд до 1 или 2... Таким образом, использование insert_multiple является ключевым здесь!   -  person klaas    schedule 18.02.2018


Ответы (5)


Является ли TinyDB лучшим выбором? Кажется, вам нужна транзакционная база данных, а TinyDB ориентирована на документы. Кроме того, из документа: Не использовать TinyDB

Если вам нужны расширенные функции или высокая производительность, TinyDB — неподходящая база данных для вас.

Ваш процесс работает очень медленно, потому что вы накапливаете данные в ОЗУ. В качестве обходного пути вы можете разделить свой csv на меньший ствол и заполнить им свой скрипт. Таким образом, память может быть чистой между каждой итерацией.

tinyDB совершенно не в состоянии справиться с таким объемом информации.

person iFlo    schedule 23.12.2016

На этой неделе у меня была похожая проблема, решение которой заключалось в использовании CachingMiddleware:

import csv
from tinydb import TinyDB
from tinydb.storages import JSONStorage
from tinydb.middlewares import CachingMiddleware

db = TinyDB('db.monitor', storage=CachingMiddleware(JSONStorage))
table = db.table('Current')

i=0

datafile = open('newData.csv', 'rb')
data=csv.reader(datafile, delimiter = ';')

for row in data:
    table.insert({'WT_ID': row[0], 'time': row[1], 'MeanCurrent': row[2], 'VapourPressure': row[3], 'MeanVoltage':row[4], 'Temperature': row[5], 'Humidity': row[6], 'BarPressure': row[7], 'RPM': row[8], 'WindSector': row[9], 'WindSpeed': row[10], 'AirDensity': row[12], 'VoltageDC': row[13], 'PowerSec': row[14], 'FurlingAngle': row[15]})
    i=i+1
    print i
person piterdias    schedule 04.11.2019

Я никогда не использовал tinyDB, но вы можете попробовать два варианта ниже.

  1. Панды в БД

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_sql.html

Pandas может читать данные csv массово и быстрее, чем чтение построчно из файла.

  1. Прочитайте CSV-файл фрагментами, а не построчно, а затем создайте для него оператор вставки вместо оператора вставки для каждой строки.
person Shijo    schedule 23.12.2016

TinyDB будет работать медленно, так как загружает все в оперативную память. Я не уверен в каких-либо хороших альтернативах, хотя вас может заинтересовать эта библиотека хранилища документов с поддержкой SQLite, которую я написал некоторое время назад:

https://github.com/skorokithakis/goatfish

Вы можете создавать индексы для некоторых полей, и это превращает все в SQL-запросы, поэтому производительность довольно приличная.

person Stavros Korokithakis    schedule 15.06.2020

Создавать файл вручную намного быстрее, если вы анализируете данные из CSV-файла. Я бы предложил что-то вроде следующего:

import json
counter = 0
with open(csv_file) as fh, open('test.db','w') as db:
    keys = None
    db.write('{"_default": {')
    spacer = ''
    for line in fh:
        if not keys:
            # This is the header row
            keys = line[:-1].replace(" ", "_").split('\t')
        else:
            counter += 1
            # These are the data rows
            values = line[:-1].split('\t')
            db.write('{}"{}":{}'.format(spacer,counter,json.dumps(dict(zip(keys, values)))))
            spacer = ','
        if counter % 1000 == 0:
            print( 'counter: {:10d}'.format(counter), end='\r')
    db.write('}}')

     
person rbf22    schedule 10.08.2020