我有一个非常大的 SQLite 文件,我想用 Python (3.9.2) 尽可能快地读取它。在每一行上我都必须做一些操作(涉及数据库外部的外部参数,所以我不能使用 SQLite create_function),所以我必须逐行读取。似乎大部分时间都花在了阅读循环中。
作为参考,我们可以考虑这个虚拟 SQLite 数据库生成器 create.py:
#!/usr/bin/env python
import argparse, contextlib, sqlite3, timeit
def create_file(rows, columns, output):
start = timeit.default_timer()
with contextlib.closing(sqlite3.connect(output)) as connection, connection, contextlib.closing(connection.cursor()) as cursor:
headers = ','.join('[headers{}] text'.format(i) for i in range(columns))
cursor.execute('CREATE TABLE [output] ({})'.format(headers))
fields = ','.join('?' for i in range(columns))
statement = 'INSERT INTO output VALUES ({})'.format(fields)
dummy_row = ["0000000000000000"] * columns
for i in range(rows):
cursor.execute(statement, dummy_row)
end = timeit.default_timer()
print("Executed in: {}".format(end-start))
if __name__ == '__main__':
parser = argparse.ArgumentParser('generate dummy file')
parser.add_argument("columns", type=int, help="number of columns")
parser.add_argument("rows", type=int, help="number of rows")
parser.add_argument('output', help='output file')
args = parser.parse_args()
create_file(args.rows, args.columns, args.output)
我们可以使用以下命令生成一个 10GB 的文件:
python create.py 50 10000000 dummy.sqlite
Executed in: 81.07768724599737
我们可以使用 SQLite 文件 reader.py 读取它:
#!/usr/bin/env python
import argparse, sqlite3, contextlib, timeit
def read_file(input):
start = timeit.default_timer()
with contextlib.closing(sqlite3.connect(input)) as connection, connection, contextlib.closing(connection.cursor()) as cursor:
cursor.execute("SELECT * from output")
for row in cursor:
pass
end = timeit.default_timer()
print("Executed in: {}".format(end-start))
if __name__ == '__main__':
parser = argparse.ArgumentParser('read file')
parser.add_argument('input', help='input file')
args = parser.parse_args()
read_file(args.input)
结果是:
python3 read.py dummy.sqlite
Executed in: 89.3538507129997
我尝试过使用 PRAGMA,批量读取(fetchmany 或 SELECT/LIMIT),生成索引,但我无法获得显着的结果(最多赢得 2-3 秒)。
作为参考,我的系统可以很快地复制文件:
cp dummy.sqlite dummy_copy.sqlite
real 0m18,464s
user 0m0,070s
sys 0m12,175s
我是否只是达到了 python+sqlite3 库的物理极限,而更快的唯一方法是更改代码语言?或者有没有人可以推荐的技巧?