【发布时间】:2020-02-25 00:43:11
【问题描述】:
由于我是 sqlite 数据库的新手,我非常感谢每一个有用的评论、答案或对有趣线程和网站的引用。这是我的情况:
我有一个包含 400 个 txt 文件的目录,每个文件的大小约为 7GB。这些文件中的相关信息被写入一个 sqlite 数据库,生成一个 17.000.000x4 的表,大约需要 1 天。稍后将仅由我查询数据库以进一步分析数据。
如果可以并行写入数据库,则可以显着加快创建数据库的整个过程。例如,我可以并行运行多个进程,每个进程仅将 400 个 txt 文件中的一个作为输入并将结果写入数据库。那么是否可以让多个进程并行写入数据库?
EDIT1: 回答 w.r.t. W4t3randWinds 评论:可以(并且更快)每个核心处理 1 个文件,将结果写入数据库并在此之后合并所有数据库。但是,使用多线程写入 1 个数据库是不可能的。
此外,我想知道创建多个数据库而不是一个大数据库是否更有效?例如,为每个 txt 文件创建一个数据库是否有意义,从而导致 400 个数据库由一个 17.000.000/400 x 4 表组成?
最后,我将数据库作为文件存储在我的机器上。但是,我还阅读了有关设置服务器的可能性。那么什么时候使用服务器有意义,更具体地说,在我的情况下使用服务器是否有意义?
请看下面我创建数据库的代码。
### SET UP
# set up database
db = sqlite3.connect("mydatabase.db")
cur = db.cursor()
cur.execute("CREATE TABLE t (sentence, ngram, word, probability);")
# set up variable to store db rows
to_db = []
# set input directory
indir = '~/data/'
### PARSE FILES
# loop through filenames in indir
for filename in os.listdir(indir):
if filename.endswith(".txt"):
filename = os.path.join(indir, filename)
# open txt files in dir
with io.open(filename, mode = 'r', encoding = 'utf-8') as mytxt:
### EXTRACT RELEVANT INFORMATION
# for every line in txt file
for i, line in enumerate(mytxt):
# strip linebreak
line = line.strip()
# read line where the sentence is stated
if i == 0 or i % 9 == 0:
sentence = line
ngram = " ".join(line.split(" ")[:-1])
word = line.split(" ")[-1]
# read line where the result is stated
if (i-4) == 0 or (i-4) % 9 == 0:
result = line.split(r'= ')[1].split(r' [')[0]
# make a tuple representing a new row of db
db_row = (sentence, ngram, word, result)
to_db.append(db_row)
### WRITE TO DATABASE
# add new row to db
cur.executemany("INSERT INTO t (sentence, ngram, word, results) VALUES (?, ?, ?, ?);", to_db)
db.commit()
db.close()
【问题讨论】:
-
通过将一个文件并行写入数据库(例如 4cores - 1 个文件)是不可能实现显着加速的。但是,您可以使用像 GNU 并行这样的工具来并行处理文件,以便轻松进行多处理,但是您受限于 sqlite 是单线程的。您已经将插入分组为块,这有望帮助您解决 n+1 问题。
-
也许我的解释不清楚。我想并行处理 x 个内核上的 x 个文件并将结果写入 x 个数据库。之后,我会将数据库合并到一个数据库中。我想知道是否可以让 x 个进程立即写入一个数据库。
-
好的,所以合并场景是有意义的。 x 个文件上的 x 个进程满足我建议的 GNU 并行的 1 对 1 核心到数据库的要求,你的最后一个问题 x 个进程/每个数据库的文件将面临我提到的限制,因为 sqlite 是单线程的。