简体   繁体   English

提高sqlite查询速度

[英]Improve sqlite query speed

I have a list of numbers (actually, percentages) to update in a database. 我有一个要在数据库中更新的数字列表(实际上是百分比)。 The query is very simple, I obtain the id of the items somewhere in my code, and then, I update these items in the database, with the list of numbers. 查询非常简单,我在代码中的某处获取了项目的ID,然后使用数字列表更新了数据库中的这些项目。 See my code: 看我的代码:

start_time = datetime.datetime.now()

query = QtSql.QSqlQuery("files.sqlite")
for id_bdd, percentage in zip(list_id, list_percentages):
    request = "UPDATE papers SET percentage_match = ? WHERE id = ?"
    params = (percentage, id_bdd)

    query.prepare(request)

    for value in params:
        query.addBindValue(value)

    query.exec_()

    elsapsed_time = datetime.datetime.now() - start_time
    print(elsapsed_time.total_seconds())

It takes 1 second to generate list_percentages, and more than 2 minutes to write all the percentages in the database. 生成list_percentages需要1秒,而将所有百分比写入数据库需要2分钟以上。 I use sqlite for the database, and there are about 7000 items in the database. 我将sqlite用于数据库,数据库中大约有7000个项目。 Is it normal that the query takes so much time ? 查询花费这么长时间是正常的吗? If not, is there a way to optimize it ? 如果没有,有没有一种方法可以对其进行优化?

EDIT: Comparison with the sqlite3 module from the std library: 编辑:与std库中的sqlite3模块进行比较:

bdd = sqlite3.connect("test.sqlite")
bdd.row_factory = sqlite3.Row
c = bdd.cursor()

request = "UPDATE papers SET percentage_match = ? WHERE id = ?"

for id_bdd, percentage in zip(list_id, list_percentages):
    params = (percentage, id_bdd)
    c.execute(request, params)

bdd.commit()
c.close()
bdd.close()

I think the QSqlQuery commits the changes at each loop lap, while the sqlite3 module allows to commit at the ends, all the different queries at the same time. 我认为QSqlQuery在每个循环圈提交更改,而sqlite3模块允许在最后提交所有不同的查询。

For the same test database, the QSqlQuery takes ~22 s, while the "normal" query takes ~0.3 s. 对于相同的测试数据库,QSqlQuery花费约22 s,而“正常”查询花费约0.3 s。 I can't believe this is just a perf issue, I must do something wrong. 我不敢相信这只是一个问题,我必须做错什么。

You need to start a transaction , and commit all the updates after the loop. 您需要启动一个transaction ,并在循环之后commit所有更新。

Not tested but should be close to: 未经测试,但应接近:

start_time = datetime.datetime.now()

# Start the transaction time
QtSql.QSqlDatabase.transaction()

query = QtSql.QSqlQuery("files.sqlite")
for id_bdd, percentage in zip(list_id, list_percentages):
    request = "UPDATE papers SET percentage_match = ? WHERE id = ?"
    params = (percentage, id_bdd)

    query.prepare(request)

    for value in params:
        query.addBindValue(value)

    query.exec_()

# commit changues
if QtSql.QSqlDatabase.commit():
   print "updates ok"

elsapsed_time = datetime.datetime.now() - start_time
print(elsapsed_time.total_seconds())

At the other hand, this question could to be a database performance issue, try to create an index on id field: https://www.sqlite.org/lang_createindex.html 另一方面,此问题可能是数据库性能问题,请尝试在id字段上创建索引: https : //www.sqlite.org/lang_createindex.html

You will need direct access to the database. 您将需要直接访问数据库。

create index on papers (id);

Do you really need to call the prepare each time? 您真的需要每次打电话给“准备”吗? to me, it seems the request doesn't change, so this "prepare" function could be moved out of loop? 在我看来,请求没有改变,所以这个“准备”功能可以移出循环吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM