Как дорого sqlite3.connect и закрыть в SQLite? - PullRequest
3 голосов
/ 19 сентября 2010

Я использую connect () и курсор () для использования SQLite

self.connector = sqlite3.connect(self.dbFile)
self.cursor = self.connector.cursor()

И close () для прекращения его использования.

self.cursor.close()

Как дорого (с точки зрения времени обработки)) они?Это настолько дорого, что использовать его нужно только в случае необходимости?Или можно использовать его несколько раз в функции?

ДОБАВЛЕНО

Я протестировал следующий простой код.proc1 () использует код, который открывается и закрывается все время, когда он выполняет запрос, а proc2 () запускается только один раз.

from sqlite import *
import timeit
import math

def proc1():
    db = SQLiteDB("./example.db", False)
    db.getOpenRunClose("SELECT * from Benchmark")
    db.getOpenRunClose("SELECT * from Benchmark")
    db.getOpenRunClose("SELECT * from Benchmark")
    db.getOpenRunClose("SELECT * from Benchmark")
    db.getOpenRunClose("SELECT * from Benchmark")
    db.getOpenRunClose("SELECT * from Benchmark")

def proc2():
    db = SQLiteDB("./example.db")
    res = db.runSQLToGetResult("SELECT * from Benchmark")
    res = db.runSQLToGetResult("SELECT * from Benchmark")
    res = db.runSQLToGetResult("SELECT * from Benchmark")
    res = db.runSQLToGetResult("SELECT * from Benchmark")
    res = db.runSQLToGetResult("SELECT * from Benchmark")
    res = db.runSQLToGetResult("SELECT * from Benchmark")
    db.close()

if __name__ == '__main__':
    t = timeit.Timer(proc1)
    count = 5000
    print t.timeit(count) / count

    t = timeit.Timer(proc2)
    count = 5000
    print t.timeit(count) / count

Результат выглядит следующим образом.

0.00157478599548
0.000539195966721

Ответы [ 3 ]

5 голосов
/ 20 сентября 2010

Соединения довольно дорогие - они соответствуют открытию файла - но курсоры не очень используются, поэтому используйте столько, сколько вам нужно [1] . стоимость означает, что транзакция запускается и особенно фиксируется, когда происходит вставка или обновление (или, если вы, конечно, создаете таблицу или индекс), даже если вы находитесь в режиме автоматической фиксации.Это связано с тем, что ядро ​​базы данных должно синхронизировать данные на диск до того, как оно завершит фиксацию (требуется для обеспечения долговечности), и это просто дорого на современном оборудовании.(Транзакция начинается с стоимости, потому что они требуют некоторой блокировки файла БД, что может оказать влияние.)

Компиляция операторов также может стоить немного;повторно использовать скомпилированные заявления, если это возможно.Конечно, вы должны делать это в любом случае.Зачем?Это потому, что вы никогда не должны помещать пользовательские данные в сгенерированный SQL;Это не только приводит к проблемам с уязвимостями SQL-инъекций, но также заставляет механизм БД перекомпилировать оператор при каждом его запуске.Скомпилированные операторы и безопаснее и (возможно) также быстрее.


[1] Конечно, глупо использовать больше курсоров, чем вам нужно.Это просто напрасная трата времени и усилий.

1 голос
/ 21 сентября 2010

Connect - это больше, чем просто открытие файла. Как только вы выполняете какие-либо запросы к базе данных, он должен проанализировать все SQL в таблице sqlite_master. Поэтому время подключения сильно зависит от сложности базы данных. Простые базы данных могут быть подключены за несколько миллисекунд, но большие базы данных займут больше. У нас время около 45 мс (более ста таблиц, несколько сотен триггеров).

1 голос
/ 21 сентября 2010

Connect - относительно дорогая операция. Хотя sqlite connect невероятно быстрый и легкий по сравнению с большинством БД. На самом деле это просто "fopen" и несколько операций чтения из основной таблицы sqlite.

В большинстве запросов будет использоваться курсор внутри системы, независимо от того, просите вы об этом или нет, это просто ручка для ссылки на большой набор строк, поэтому явный курсор будет стоить вам очень мало. Для обработки больших наборов результатов курсоры на самом деле более эффективны, вы можете получить доступ к первым строкам результатов, как только они станут доступны, у вас есть только ограниченное количество строк в памяти за раз, и вы можете быстро выйти из длинного запроса, если решить, что ответ не то, что вы хотели.

Я бы также рекомендовал «подготовленные» заявления. Это лучшая безопасность, и, если вы разумно кешируете запросы, это избавит sqlite от постоянного разбора одного и того же фрагмента sql.

...