我已经生成了一个巨大的SQLite数据库,需要从中获取一些数据。我写了一些脚本来做这个,并且分析让我们得出一个不幸的结论,即写入过程需要大约。当前设置为3天。我尽可能简单地编写了脚本,以尽可能快地完成。
我想知道你是否有一些技巧可以加速整个过程。数据库有一个唯一的索引,但我查询的列不是(因为那些行重复)。
在这里使用任何多处理Python库是否有意义?
脚本将是这样的:
import sqlite3
def write_from_query(db_name, table_name, condition, content_column, out_file):
'''
Writes contents from a SQLite database column to an output file
Keyword arguments:
db_name (str): Path of the .sqlite database file.
table_name (str): Name of the target table in the SQLite file.
condition (str): Condition for querying the SQLite database table.
content_colum (str): Name of the column that contains the content for the output file.
out_file (str): Path of the output file that will be written.
'''
# Connecting to the database file
conn = sqlite3.connect('zinc12_drugnow_nrb(copy).sqlite')
c = conn.cursor()
# Querying the database and writing the output file
c.execute('SELECT ({}) FROM {} WHERE {}'.format(content_column, table_name, condition))
with open(out_file, 'w') as outf:
for row in c:
outf.write(row[0])
# Closing the connection to the database
conn.close()
if __name__ == '__main__':
write_from_query(
db_name='my_db.sqlite',
table_name='my_table',
condition='variable1=1 AND variable2<=5 AND variable3="Zinc_Plus"',
content_column='variable4',
out_file='sqlite_out.txt'
)
感谢您的帮助,我期待着您的建议!
编辑: 有关数据库的更多信息:
答案 0 :(得分:1)
我假设您正在运行write_from_query函数以进行大量查询。
如果是这样,问题是过滤条件中缺少索引
这导致以下结果:对于您执行的每个查询,sqlite将遍历整个50GB的数据并检查您的条件是否成立。这非常低效。
最简单的方法是在列上拍打索引
另一种方法是制定包含多个案例的较少查询,然后再次循环该数据以将其拆分为不同的文件。然而,这可以做得多好取决于数据的结构。
我不确定多处理/线程,sqlite并不是真正用于并发,但我想它可以解决,因为你只读数据......
答案 1 :(得分:0)
您可以在自己的程序中转储内容并过滤 - 或者将索引添加到您在条件中使用的所有列。
向所有列添加索引需要很长时间。 但对于许多不同的查询,没有其他选择。
没有多处理可能无济于事。 SSD可能,或64GiB Ram。但是索引不需要它们,查询也会在普通磁盘上快速执行。
总之,您创建了一个数据库,但没有为要查询的列创建索引。对于8Mio行,这不会起作用。
答案 2 :(得分:0)
虽然将这些数据实际写入文件的过程需要一段时间,但我希望它更像是几分钟而不是几天。在50MB / s的连续写入速度下,15GB可以在大约5分钟内完成。
我怀疑问题在于查询/缺少索引。我建议尝试根据您需要过滤的列组合来构建复合索引。正如您将从文档here中看到的那样,您实际上可以根据需要为索引添加任意数量的列。
只是为了让你意识到添加索引会减慢数据库的插入/更新速度,因为每次它需要在相关索引中找到适当的位置来添加数据以及将数据附加到表的末尾,但是这可能是加速查询的唯一选择。
答案 3 :(得分:0)
我会看一下独特的指数!但同时我偶然发现了另一件事......很抱歉在这里为我的问题写了一个自己的答案,但我觉得这对组织来说更好......
我当时认为.fetchall()
命令也可以加快整个过程,但我发现sqlite3文档对此有点简短...会像
with open(out_file, 'w') as outf:
c.excecute ('SELECT * ...')
results = c.fetchmany(10000)
while results:
for row in results:
outf.write(row[0])
results = c.fetchmany(10000)
有意义吗?