конвертировать очень большие json в sql с помощью Ijson - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть файл 60GB json, и я хочу преобразовать его в sql с i json. (Я перепробовал много программ и инструментов. Они не были полезны, и моя система зависала.

Примечание : это не дублируется! Я вижу весь код об этих методах и написал это, но все еще у меня очень медленный код.

вот мой код:

import json
import sqlite3
import ijson 
import threading


def solve():
    with sqlite3.connect("filename.db") as conn:
        try:
            conn.execute('''
            CREATE TABLE IF NOT EXISTS mytable(
            username       VARCHAR(225) 
            ,phone         INTEGER   
            ,id            INTEGER PRIMARY KEY

            );''')
        except :
            pass
        keys = ["username", "phone" ,  "id"]
        with open('VERYBIGJSON.json' , 'r' , encoding='utf-8') as json_file:
            data = ijson.parse(json_file ,  multiple_values=True)

            for prefix, event, value in data:
                if str(event) == 'start_map':
                    _u = None

                if prefix == "id" :
                    _id = value

                if prefix == "username":
                    _u = value

                if prefix == "phone":
                    _p = value

                try:
                    if  str(event) == 'end_map' :
                        values = (_u , _p , _id)
                        cmd = """INSERT INTO mytable (username , phone , id)  VALUES(
                                    ?,
                                    ?,
                                    ?

                                );"""
                        conn.execute(cmd, values)



                        conn.commit()

                except Exception as e:
                    #print (str(e))
                    continue

if __name__ == '__main__':
    t=[]
    for i in range(1000):
        t.append(threading.Thread(target=solve))


    for i in t: 
        i.start() 

    for i in t:
        i.join() 

Я протестировал как многопоточный, так и многопроцессорный метод, и все же мой код работает очень очень медленно! (только ) 10КБ моей sql базы данных будет генерироваться в секунду ).

Я хочу сделать это очень эффективно.

мой json пример:

{"message":"{\"_\":\"user\",\"delete\":{\"test\":true},\"flags\":2067,\"id\":11111110,\"phone\":\"xxxxxxxxxx\",\"photo\":{\"_\":\"userProfilePhoto\",\"photo_id\":\"xxxxxxxxxx\",\"photo_small\":{\"_\":\"file\",\"dcs\":4,\"volume_id\":\"8788701\",\"local_id\":385526},\"photo\":{\"_\":\"file\",\"dcs\":4,\"local_id\":385528}},\"status\":{\"_\":\"userStat\",\"online\":1566173427}}","phone":"xxxxxxxxxx","@version":"1","id":11111110}
{"index": {"_type": "_doc", "_id": "-Lcy4m8BAObvGO9GAsFa"}}

....

Пожалуйста, дайте мне идею улучшить скорость кода.

ОБНОВЛЕНИЕ: в соответствии с комментариями я написал код для преобразования моего большого json файл в .csv, но все же он такой медленный, но быстрее, чем метод 1!

вот код:

import json
import sqlite3
import ijson 
from multiprocessing import Process
import csv
import pandas as pd
from pandas.io.json import json_normalize
from multiprocessing import Process
import threading

def solve():

        with open('VERYBIGJSON.json' , 'r' , encoding='utf-8') as json_file:
            data = ijson.parse(json_file ,  multiple_values=True )

            for prefix, event, value in data:

                if str(event) == 'start_map':

                    _u = None




                if prefix == "id" :
                    _id = value

                if prefix == "username":
                    _u = value

                if prefix == "phone":
                    _p = value



                if  str(event) == 'end_map' :

                            values = [{'username':'{}'.format(_u) , 'id':'{}'.format(_id) , 'phone':'{}'.format(_p)}] #converting to json for add to 'json_normalize'


                            df = json_normalize(values)
                            df.to_csv('test.csv', index=False, mode='a' ,  encoding='utf-8' , header=False)



if __name__ == '__main__':
    solve()

Также с библиотекой JsonSlicer:

def solve():


        with open('VERYBIGJSON.json' , 'r' , encoding='utf-8') as json_file:
            for key   in JsonSlicer(json_file , (None , None) ) :
                print (key)


if __name__ == '__main__':
    solve()

я получаю эту ошибку:

    for key   in JsonSlicer(json_file , (None , None) ) :
RuntimeError: YAJL error: parse error: trailing garbage
          d_from":"telegram_contacts"} {"index": {"_type": "_doc", "_i
                     (right here) ------^

Я думаю, эта библиотека не поддерживает мой json файл.

...