python - 在python中将数据库表写入文件的最快方法

标签 python database performance

我正在尝试从数据库中提取大量数据并将其写入 csv 文件。我正在尝试找出最快的方法来做到这一点。我发现在 fetchall 的结果上运行 writerows 比下面的代码慢 40%。

with open(filename, 'a') as f:
    writer = csv.writer(f, delimiter='\t')
    cursor.execute("SELECT * FROM table")
    writer.writerow([i[0] for i in cursor.description])

    count = 0
    builder = []
    row = cursor.fetchone()
    DELIMITERS = ['\t'] * (len(row) - 1) + ['\n']
    while row:
        count += 1
        # Add row with delimiters to builder 
        builder += [str(item) for pair in zip(row, DELIMITERS) for item in pair]
        if count == 1000:
            count = 0
            f.write(''.join(builder))
            builder[:] = []
        row = cursor.fetchone()
    f.write(''.join(builder))

编辑:我使用的数据库是我工作的小公司所独有的,因此不幸的是我无法提供这方面的太多信息。我使用 jpype 来连接数据库,因为唯一的连接方法是通过 jdbc 驱动程序。我正在运行 cPython 2.7.5;很想使用 PyPy,但它不适用于 Pandas。

由于我要提取如此大量的行,因此我在使用 fetchall 时犹豫不决,因为担心会耗尽内存。 row 具有相当的性能,并且更美观,所以我想我会使用它。非常感谢!

最佳答案

鉴于您给我们提供的信息很少,很难说得更具体,但是……

我已将您的代码包装为函数,并编写了三个替代版本:

def row():
    with open(filename, 'w') as f:
        writer = csv.writer(f, delimiter='\t')
        cursor = db.execute("SELECT * FROM mytable")
        writer.writerow([i[0] for i in cursor.description])
        for row in cursor:
            writer.writerow(row)

def rows():
    with open(filename, 'w') as f:
        writer = csv.writer(f, delimiter='\t')
        cursor = db.execute("SELECT * FROM mytable")
        writer.writerow([i[0] for i in cursor.description])
        writer.writerows(cursor)

def rowsall():
    with open(filename, 'w') as f:
        writer = csv.writer(f, delimiter='\t')
        cursor = db.execute("SELECT * FROM mytable")
        writer.writerow([i[0] for i in cursor.description])
        writer.writerows(cursor.fetchall())

请注意,最后一个是您所说的您尝试过的。

现在,我编写了这个测试驱动程序:

def randomname():
    return ''.join(random.choice(string.ascii_lowercase) for _ in range(30))

db = sqlite3.connect(':memory:')
db.execute('CREATE TABLE mytable (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR)')
db.executemany('INSERT INTO mytable (name) VALUES (?)',
               [[randomname()] for _ in range(10000)])

filename = 'db.csv'

for f in manual, row, rows, rowsall:
    t = timeit.timeit(f, number=1)
    print('{:<10} {}'.format(f.__name__, t))

结果如下:

manual     0.055549702141433954
row        0.03852885402739048
rows       0.03992213006131351
rowsall    0.02850699401460588

因此,您的代码花费的时间几乎是调用 fetchall 的两倍和writerows在我的测试中!

但是,当我对其他数据库重复类似的测试时,rowsallmanual 快 20% 到慢 15% (绝不会慢 40%,而是慢 15%)……但是 rowrows总是明显快于 manual .

我认为解释是您的自定义代码明显慢于 csv.writerows ,但在某些数据库中,使用 fetchall而不是fetchone (或者只是迭代光标)会显着减慢速度。对于内存中的 sqlite3 数据库来说,情况并非如此,原因是 fetchone正在做与 fetchall 相同的工作然后一次给你一张 list ;使用远程数据库,fetchone可以执行任何操作,从获取所有行,到一次获取缓冲区,再到一次获取一行,使其可能比 fetchall 慢得多或快得多,取决于您的数据。

但是为了获得真正有用​​的解释,您必须准确地告诉我们您正在使用哪个数据库和库(以及哪个 Python 版本 - CPython 3.3.2 的 csv 模块似乎比 CPython 2.7 快得多。 5 的版本,PyPy 2.1/2.7.2 似乎也比 CPython 2.7.5 更快,但是其中任何一个也可能更快地运行您的代码......)等等。

关于python - 在python中将数据库表写入文件的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21270148/

相关文章:

performance - 基于提示的 Oracle SQL 调优 - 最近版本有什么好处吗?

windows - 将目录添加到 Windows Path 变量会影响性能吗?

python - TensorFlow 中的事件正则化器

python - Numpy.copy 无法按预期进行随机采样

mysql - 如何使用 JOIN 从日期中选择不同的一天

php - 如何通过 Laravel 中的类别显示帖子

database - 用于按多个日期值排序的 MySQL 查询

c# & java 套接字和字节数据读取开销

python - 将条件列表传递给要检查的函数

python - __get__ 一个简单函数的目的