Python SQLite - 慢速更新记录

时间:2017-02-07 22:42:15

标签: python sqlite

我有一个脚本,它将存储在数据库中的日期从Unix Time(epoch)转换为人类可读的格式。有30,000条记录 要从数据库中提取数据,将其转换,然后将其打印到屏幕上非常快。但是,要从数据库中提取数据,请将其转换并执行"更新"更新记录的声明非常慢 无论如何,是否有优化以下代码,以加快我有30,000条记录的过程?

    cur.execute('select Atime from Hash where Atime like (?) ', (test,))
    results = cur.fetchall()
    for row in results:
        convertedtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime((float(row[0]))))
        print convertedtime
        cur.execute('Update Hash set Atime = (?) where Atime = (?)', (convertedtime, row[0]))
    con.commit()

con.commit()在for循环之外,因此在每次迭代后提交记录都不是问题。

1 个答案:

答案 0 :(得分:4)

主要的性能问题是你从SQLite中提取数据,将其加载到Python中,在Python中转换它,然后将其重新放回数据库 一次一个日期 即可。这永远不会有效。

相反,use SQLite's own built in date and time functions。看起来atime是Unix纪录时间。

update hash set atime = datetime(atime, 'unixepoch', 'localtime');

可能不希望在当地时区存储日期 。时区变得复杂,并且夏令时间缺失和重叠时间......它只会导致眼泪。您绝对不希望在本地时区存储日期时间而不指示该时区是什么!

除非您有充分的理由,否则请将其存储为UTC。

update hash set atime = datetime(atime, 'unixepoch');

通常,如果您想做SQLite不支持的事情, 创建用户定义的函数并在查询中使用 。这比使用内置的SQLite函数效率低,但比选择,转换和更新更有效。

它看起来像这样。

def epoch_to_iso8601(epoch):
    return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime((float(epoch))))

con.create_function("epoch_to_iso8601", 1, epoch_to_iso8601)

然后,您可以在查询中使用epoch_to_iso8601

update hash set atime = epoch_to_iso8601(atime);

请注意,这与存储过程不同。由于没有SQLite服务器,所有代码都在您的进程中运行,此功能是按进程执行的。

请参阅sqlite3.create_function

这里真正的问题是你将日期时间存储为字符串 。这使得他们工作缓慢而笨拙。这意味着您必须选择单个格式。这意味着您必须解析该格式以对其执行任何操作。这意味着你不能使用内置的SQLite日期和时间函数(稀疏,因为它们)。

您真正想要做的是将atime作为Unix纪元时间,并根据您的查询需要对其进行格式化。

select datetime(atime, 'unixepoch') from hash;

幸运的是,SQLite的类型非常松散,并且会将文本atime字段转换为数字,但会导致性能和存储损失。

理想情况下,您希望更改atime以使用datetime类型,但这在SQLite中很难实现。它不支持删除或修改现有列。相反,您必须将数据转储到表中,重新创建表并导入数据。这应该非常快,只有30,000条记录。

切换到CSV模式,将输出发送到文件,然后选择所有内容。

sqlite> .mode csv hash
sqlite> .output hash.out
sqlite> select * from hash;

删除现有表并重新创建,但atimedatetime

sqlite> drop table hash;
sqlite> create table hash ( atime datetime, and the other columns );

导入转储。

sqlite> .import hash.out hash