当涉及到以注释开头的 SQL 查询时,Python sqlite3 模块是不是存在错误和缓慢?

Posted

技术标签:

【中文标题】当涉及到以注释开头的 SQL 查询时,Python sqlite3 模块是不是存在错误和缓慢?【英文标题】:Is the Python sqlite3 module bugged and slow when it comes to SQL queries that start with comments?当涉及到以注释开头的 SQL 查询时,Python sqlite3 模块是否存在错误和缓慢? 【发布时间】:2020-01-27 00:32:41 【问题描述】:

我注意到,如果 SQL 查询以使用 --comment 格式的注释开头,我的 sqlite3 查询需要 375 倍的时间。这是正常行为吗?它是内置 sqlite3 模块中的错误吗?

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

编辑:我发现 /* */ style cmets 的行为相同。

【问题讨论】:

反转调用(在未注释查询之后执行注释查询)。这种情况下的结果是什么?结果对您有什么建议吗? 如果我反转它们,结果基本上是一样的:sqlfast: 0.058180847000000036 sqlslow: 21.596948887 我不知道它为什么会这样做。 我添加了一个答案,我认为可以解释这种行为。 【参考方案1】:

从表面上看,性能似乎与评论有关,我在 sqlite3 上看到了类似的结果(20 秒和 0.05 秒)。但我认为还不止于此。

我将代码中的 sqlite3 替换为 apsw 包,该包具有不同的事务处理,使用它时,我看到两个测试都用了 20 秒。请注意,apsw 不会像 sqlite3 那样自动为您开始事务。

然后我明确地在 43k 插入周围包含了一个事务开始/提交,两次都花费了 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 查询时,Python sqlite3 模块是不是存在错误和缓慢?的主要内容,如果未能解决你的问题,请参考以下文章

c#模糊查询

如何将 GraphQL 查询中的数据传递到以编程方式生成的页面上?

如何将数据压缩到以时间戳开头的单行

如何将类名添加到以特定 id 开头的所有元素?

将捆绑数据传递到以viewPager开头的片段

Gulp:将文件复制到以特定字符串开头的多个文件夹