当涉及到以注释开头的 SQL 查询时,Python sqlite3 模块是否有问题并且速度很慢?
Is the Python sqlite3 module bugged and slow when it comes to SQL queries that start with comments?
我注意到,如果 SQL 查询以使用 --comment 格式的注释开头,我的 sqlite3 查询将花费 375 倍的时间。这是正常行为吗?是内置sqlite3模块的bug吗?
import pathlib
import sqlite3
import timeit
def test_do(sql):
db_path = pathlib.Path("./test.sqlite3")
con = sqlite3.connect(db_path)
cursor = con.cursor()
table_sql: str = f"""
CREATE TABLE IF NOT EXISTS test (
id INTEGER PRIMARY KEY)"""
cursor.execute(table_sql)
for i in range(1, 43000):
cursor.execute(sql, [i])
con.commit()
db_path.unlink()
sqlslow = f"""
--comment
INSERT INTO "test" ("id") VALUES (?)
"""
sqlfast = f"""
INSERT INTO "test" ("id") VALUES (?)
"""
starttimeslow = timeit.default_timer()
test_do(sqlslow)
print(f"sqlslow: {timeit.default_timer() - starttimeslow}")
starttimefast = timeit.default_timer()
test_do(sqlfast)
print(f"sqlfast: {timeit.default_timer() - starttimefast}")
结果:
sqlslow: 21.521265994
sqlfast: 0.05736106100000171
编辑:我发现 /* */ 样式注释有相同的行为。
从表面上看,性能似乎与评论有关,我在 sqlite3 上看到了类似的结果(20 秒和 0.05 秒)。不过我觉得还不止这些。
我用 apsw 包替换了您代码中的 sqlite3,它具有不同的事务处理,并且在使用它时,我看到两个测试都需要 20 秒。请注意,apsw 不会自动为您开始事务,而 sqlite3 会。
然后我明确地在 43k 插入周围包含了一个事务 begin/commit,两次都花费了 0.05 秒。这是有道理的,因为此代码在事务中应该 运行 更快。
这一切都向我表明,sqlite3 在一种情况下(单行 INSERT)使用了事务,而在另一种情况下(带注释和 INSERT 的多行语句)则没有。另外,sqlite3 的事务处理虽然旨在为用户简化操作,但似乎有点奇怪。
实际上,如果我明确插入以下开始事务,则 sqlite3 结果都很快(0.05 秒):
cursor.execute(table_sql)
cursor.execute("begin") # add this
for i in range(1, 43000):
cursor.execute(sql, [i])
con.commit()
sqlite3 测试的输出现在是:
sqlslow: 0.051317919000000004
sqlfast: 0.05007833699999999
我注意到,如果 SQL 查询以使用 --comment 格式的注释开头,我的 sqlite3 查询将花费 375 倍的时间。这是正常行为吗?是内置sqlite3模块的bug吗?
import pathlib
import sqlite3
import timeit
def test_do(sql):
db_path = pathlib.Path("./test.sqlite3")
con = sqlite3.connect(db_path)
cursor = con.cursor()
table_sql: str = f"""
CREATE TABLE IF NOT EXISTS test (
id INTEGER PRIMARY KEY)"""
cursor.execute(table_sql)
for i in range(1, 43000):
cursor.execute(sql, [i])
con.commit()
db_path.unlink()
sqlslow = f"""
--comment
INSERT INTO "test" ("id") VALUES (?)
"""
sqlfast = f"""
INSERT INTO "test" ("id") VALUES (?)
"""
starttimeslow = timeit.default_timer()
test_do(sqlslow)
print(f"sqlslow: {timeit.default_timer() - starttimeslow}")
starttimefast = timeit.default_timer()
test_do(sqlfast)
print(f"sqlfast: {timeit.default_timer() - starttimefast}")
结果:
sqlslow: 21.521265994
sqlfast: 0.05736106100000171
编辑:我发现 /* */ 样式注释有相同的行为。
从表面上看,性能似乎与评论有关,我在 sqlite3 上看到了类似的结果(20 秒和 0.05 秒)。不过我觉得还不止这些。
我用 apsw 包替换了您代码中的 sqlite3,它具有不同的事务处理,并且在使用它时,我看到两个测试都需要 20 秒。请注意,apsw 不会自动为您开始事务,而 sqlite3 会。
然后我明确地在 43k 插入周围包含了一个事务 begin/commit,两次都花费了 0.05 秒。这是有道理的,因为此代码在事务中应该 运行 更快。
这一切都向我表明,sqlite3 在一种情况下(单行 INSERT)使用了事务,而在另一种情况下(带注释和 INSERT 的多行语句)则没有。另外,sqlite3 的事务处理虽然旨在为用户简化操作,但似乎有点奇怪。
实际上,如果我明确插入以下开始事务,则 sqlite3 结果都很快(0.05 秒):
cursor.execute(table_sql)
cursor.execute("begin") # add this
for i in range(1, 43000):
cursor.execute(sql, [i])
con.commit()
sqlite3 测试的输出现在是:
sqlslow: 0.051317919000000004
sqlfast: 0.05007833699999999