Python 将大空间分隔文件解析为sqlite

Python 将大空间分隔文件解析为sqlite,python,multithreading,python-3.x,sqlite,Python,Multithreading,Python 3.x,Sqlite,我正在尝试将一个大空间分隔文件(3GB或更高)解析到sqlite数据库中,以便进行其他处理。该文件目前大约有2000多万行数据。我已经尝试过多线程处理,但由于某种原因,它停止了大约1500行,并没有继续。我不知道我是否做错了什么。有人能给我指一下正确的方向吗 一个进程的插入工作正常,但是太慢了(当然!!!)。它已经运行了七个多小时,甚至还没有超过第一组字符串。DB文件的大小仍然是25MB,甚至不接近它必须包含的记录数 请引导我加快速度。我还有一个大文件要处理(超过5GB),这可能需要几天时间 这

我正在尝试将一个大空间分隔文件(3GB或更高)解析到sqlite数据库中,以便进行其他处理。该文件目前大约有2000多万行数据。我已经尝试过多线程处理,但由于某种原因,它停止了大约1500行,并没有继续。我不知道我是否做错了什么。有人能给我指一下正确的方向吗

一个进程的插入工作正常,但是太慢了(当然!!!)。它已经运行了七个多小时,甚至还没有超过第一组字符串。DB文件的大小仍然是25MB,甚至不接近它必须包含的记录数

请引导我加快速度。我还有一个大文件要处理(超过5GB),这可能需要几天时间

这是我的密码:

1 import time
2 import queue
3 import threading
4 import sys
5 import sqlite3 as sql
6
7 record_count = 0
8 DB_INSERT_LOCK = threading.Lock()
9
10 def process_data(in_queue):
11     global record_count
12     try:
13         mp_db_connection = sql.connect("sequences_test.sqlite")
14         sql_handler = mp_db_connection.cursor()
15     except sql.Error as error:
16         print("Error while creating database connection: ", error.args[0])
17     while True:
18         line = in_queue.get()
19         # print(line)
20         if (line[0] == '@'):
21             pass
22         else:
23             (sequence_id, field1, sequence_type, sequence_count, field2, field3,
24               field4, field5, field6, sequence_info, kmer_length, field7, field8,
25               field9, field10, field11, field12, field13, field14, field15) =     
                                                                   line.expandtabs(1).split(" ")
26
27             info = (field7 + " " + field8 + " " + field9 + " " + field10 + " " +
28                      field11 + " " + field12 + " " + field13 + " " + field14 + " "
29                      + field15)
30
31             insert_tuple = (None, sequence_id, field1, sequence_type, sequence_count,
32                              field2, field3, field4, field5, field6, sequence_info,
33                               kmer_length, info)
34             try:
35                 with DB_INSERT_LOCK:
36                     sql_string = 'insert into sequence_info \
37                                    values (?,?,?,?,?,?,?,?,?,?,?,?,?)'
38                     sql_handler.execute(sql_string, insert_tuple)
39                     record_count = record_count + 1
40                     mp_db_connection.commit()
41             except sql.Error as error:
42                 print("Error while inserting service into database: ", error.args[0])
43             in_queue.task_done()
44
45 if __name__ == "__main__":
46     try:
47         print("Trying to open database connection")
48         mp_db_connection = sql.connect("sequences_test.sqlite")
49         sql_handler = mp_db_connection.cursor()
50         sql_string = '''SELECT name FROM sqlite_master \
51                          WHERE type='table' AND name='sequence_info' '''
52         sql_handler.execute(sql_string)
53         result = sql_handler.fetchone()
54         if(not result):
55             print("Creating table")
56             sql_handler.execute('''create table sequence_info
57                                 (row_id integer primary key, sequence_id real, field1 
58                                    integer, sequence_type text, sequence_count real,
59                                  field2 integer, field3 text,
60                                  field4 text, field5 integer, field6 integer,
61                                  sequence_info text, kmer_length text, info text)''')
62             mp_db_connection.commit()
63         else:
64             pass
65         mp_db_connection.close()
66     except sql.Error as error:
67         print("An error has occured.: ", error.args[0])
68
69     thread_count = 4
70     work = queue.Queue()
71
72     for i in range(thread_count):
73         thread = threading.Thread(target=process_data, args=(work,))
74         thread.daemon = True
75         thread.start()
76
77     with open("out.txt", mode='r') as inFile:
78         for line in inFile:
79             work.put(line)
80
81     work.join()
82
83     print("Final Record Count: ", record_count)
我之所以有一个锁,是因为使用sqlite,我目前没有办法将文件批量提交到DB中,因此我必须确保每次线程插入记录时,DB的状态都已提交

我知道在繁杂的事情中使用expandtabs调用会损失一些处理时间,但要对接收到的文件进行后处理以对其进行简单拆分有点困难。我将继续尝试这样做,以减少工作量,但我至少需要多线程来工作

编辑:


我将expandtabs和split part移动到处理之外。因此,我处理该行并将其作为元组插入队列中,这样线程就可以拾取该行并直接将其插入数据库中。我本来希望用它节省不少时间,但现在我在使用sqlite时遇到了问题。它说无法插入数据库,因为它已被锁定。我认为这更像是锁定部分的线程同步问题,因为我在下面的关键部分有一个独占锁。有人能详细说明一下如何解决这个问题吗?

我不认为多线程在那里有多大用处。您可能应该编写一个生成器函数,将文件处理为元组,然后使用multihtreading插入元组将不会有帮助

您必须做的第一件事是不要根据 速度是250倍


若要在中断时不丢失所有工作,除了以前的响应之外,只需提交每10000或100000条记录,请尝试:

  • 使用来自的
    executemany
  • 使用Pypy

为这么大的文件编写生成器是个好主意吗?它的大小为3 GB。内存问题等?这就是为什么你使用生成器而不是列表的确切原因。实际上,这是个好主意。我没有意识到这一点。无论如何,速度都在加快。我可以看到DB大小随着插入而增加。我想检查是否有记录,所以我停止了脚本。数据库大小变为零。提交在什么时候发生?或者什么时候我需要进行提交?谢谢你的帮助。如果你觉得有必要在这之后对某些内容进行微调,那么有以下问题: