将大型 python 列表传递到 SQLite SELECT 语句时如何提高性能?
Posted
技术标签:
【中文标题】将大型 python 列表传递到 SQLite SELECT 语句时如何提高性能?【英文标题】:How can I boost performance when passing large python lists into SQLite SELECT statements? 【发布时间】:2022-01-20 12:36:22 【问题描述】:在循环大型 python 列表中的字符串并将它们传递到 SQLite SELECT 语句以返回值时,我遇到了巨大的性能下降,每个循环需要 0.5 到 0.7 秒。 (10K 字符串约 2 小时)
在普遍搜索之后,我不确定如何实现一种方法,以便将列表“批量”导出到更少的合并查询中,以期加快速度。
我有这个从函数生成的文件名列表:
documents = ['value1.xlsx', 'value2.docx', 'value3.txt', 'value4.csv', ...]
我还有一个 1GB 的大型数据库,其中包含唯一的文件名和文件哈希。
def iterate_documents(cur, documents):
i = 0
output = [] # Declare Empty List
while i < len(documents):
# Returning the MD5 Hash of a Passed File Name
match = cur.execute('SELECT md5hash FROM hash_table WHERE name=?', (documents[i],)).fetchone()
# If a File Name hasn't been seen by the DB, say the hash is "Unknown"
if match is None or len(match) == 0:
match = "Unknown"
else:
match = match[0]
output.append(match) # Append the match or 'Unknown' to the Output List
i += 1
return output
示例输出:hashes = [hash-1, hash-2, Unknown, value-4, ...]
接下来我要做的是使用有序输出来匹配元组(documents[i], hashes[i])
中的文档和哈希。示例:('value1.xlsx', 'hash-1')
所以我需要iterate_documents()
值保持传递顺序。到目前为止,蛮力循环是我得到的最好的!
【问题讨论】:
【参考方案1】:因为它只有 10k 个项目,我可能只从数据库中获取您需要的项目,然后在本地进行更多匹配:
import sqlite3
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i + n]
conn = sqlite3.connect('test.db')
conn.execute('''
CREATE TABLE IF NOT EXISTS hash_table(
name TEXT PRIMARY KEY NOT NULL,
md5hash TEXT
);
''')
conn.execute("INSERT INTO hash_table(name,md5hash) VALUES ('value1.xlsx', 'some hash of value1.xlsx');")
conn.execute("INSERT INTO hash_table(name,md5hash) VALUES ('value2.docx', 'some hash of value2.docx');")
documents = ['value1.xlsx', 'value2.docx', 'value3.txt', 'value4.csv']
lookup =
## -----------------------
## load the lookup in chunks due to limits of SQLLite
# ## -----------------------
chunck_size = 100
for chunc in chunks(documents, chunck_size):
sql = f"SELECT name, md5hash FROM hash_table WHERE name in (','.join(['?']*len(chunc)))"
lookup = **lookup, **dict(conn.execute(sql, chunc).fetchall())
## -----------------------
doc_with_hash = doc: lookup.get(doc, "Unknown") for doc in documents
print(doc_with_hash)
这应该给你:
'value1.xlsx': 'some hash of value1.xlsx',
'value2.docx': 'some hash of value2.docx',
'value3.txt': 'Unknown',
'value4.csv': 'Unknown'
【讨论】:
【参考方案2】:你有几个 Python 性能的选择,而不需要做太多的代码修改。
1.) 你可以使用 PyPy
这是最简单的方法
PyPy 是一种运行时解释器,它比完全解释型语言快,但比完全编译型语言(如 C)慢。
PyPY Link
2.) 你可以尝试多线程或并行处理
这会更难
Threading Docs
通过代码修改,您也有几个选择。
1.) 使用 for 循环而不是 while 循环
for 循环在 python 中更快,但在 C 中却没有
Comparing for loops to while loops
2.) 不要将变量 documents
传递给函数
变量documents
是一个可变值,它会随着变大而变化。
这会导致函数出现问题,因为您每次都在重新创建 var
【讨论】:
以上是关于将大型 python 列表传递到 SQLite SELECT 语句时如何提高性能?的主要内容,如果未能解决你的问题,请参考以下文章
如何将大型 JSON 数据从服务器存储到 SQLITE Android?
如何通过单击按钮将 Listview 中的数据传递到购物车列表(新活动)。我插入到 listview 的数据正在使用 SQLite