0

我有一个非常大的 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 库的物理极限,而更快的唯一方法是更改​​代码语言?或者有没有人可以推荐的技巧?

4

0 回答 0