Модуль Python sqlite3 прослушивается и работает медленно, когда дело доходит до SQL запросов, начинающихся с комментариев? - PullRequest
0 голосов
/ 27 января 2020

Я заметил, что мой запрос sqlite3 занимает 375 раз дольше, если запрос SQL начинается с комментария в формате --comment. Это нормальное поведение? Это ошибка во встроенном модуле 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

Редактировать: я обнаружил то же поведение с / * * / стилем комментариев.

1 Ответ

0 голосов
/ 27 января 2020

На первый взгляд может показаться, что производительность связана с комментарием, и я вижу аналогичные результаты с sqlite3 (20 секунд и 0,05 секунды). Но я думаю, что это немного больше.

Я заменил sqlite3 в вашем коде на пакет apsw , который имеет различную обработку транзакций, и при его использовании я видел 20 секунд для обоих тесты. Обратите внимание, что apsw автоматически не начинает транзакцию для вас, что делает sqlite3.

Затем я явно включил транзакцию начала / фиксации вокруг вставок 43k, и оба раза это занимало 0,05 с. Это имеет смысл, потому что этот код должен выполняться быстрее внутри транзакции.

Все это говорит мне о том, что sqlite3 использует транзакцию в одном случае (одна строка INSERT), а не в другом случае (многостраничный строка с комментарием и INSERT). Кроме того, кажется, что обработка транзакций в sqlite3, хотя и предназначена для упрощения работы пользователя, немного странна.

И, действительно, если я вставлю следующую транзакцию begin в явном виде, результаты 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
...