我正在尝试将大空格分隔文件(3 GB及更高版本)解析为sqlite数据库以进行其他处理。该文件目前有大约2千万行数据。我尝试过多线程,但由于某种原因,它停止了大约1500行并且没有继续。我不知道我做错了什么。有人可以指出我正确的方向吗?
插入工作正常,只有一个过程,但是太慢了(当然!!!)。它已运行超过七个小时,甚至没有超过第一组字符串。 DB文件仍然是25 MB大小,甚至没有接近它必须包含的记录数。
请引导我加快速度。我还有一个更大的文件(超过5 GB),这可能需要数天。
这是我的代码:
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,我目前没有办法将我的文件批量提交到数据库中,因此我必须确保每次线程插入记录时,数据库的状态承诺。
我知道我在使用expandtabs调用时会丢失一些处理时间,但是对于我正在接收的文件进行简单的拆分来处理它有点困难。我将继续尝试这样做,以减少工作量,但我至少需要多线程才能工作。
编辑:
我移动了expandtabs并在处理之外拆分了部分。因此,我处理该行并作为元组插入到队列中,以便线程可以将其拾取并直接将其插入到DB中。我希望能节省相当多的时间,但现在我遇到了sqlite的问题。它说无法插入db,因为它已被锁定。我认为这更多是锁定部分的线程同步问题,因为我在下面的关键部分有一个独占锁。有人可以详细说明如何解决这个问题吗?
答案 0 :(得分:2)
我不希望多线程在那里有很多用处。您应该编写一个生成器函数,将文件处理为元组,然后使用executemany
答案 1 :(得分:0)
答案 2 :(得分:0)
除了之前的回复,请尝试:
executemany