Я использовал python с СУБД (MySQL и PostgreSQL), и я заметил, что действительно не понимаю, как использовать курсор.
Обычно скрипт подключается к БД через клиентский DB-API (например, psycopg2 или MySQLdb):
connection = psycopg2.connect(host='otherhost', etc)
Затем создается курсор:
cursor = connection.cursor()
А затем можно выдавать запросы и команды:
cursor.execute("SELECT * FROM etc")
Интересно, где же результат запроса? это на сервере? или немного на моем клиенте и немного на моем сервере? А затем, если нам нужно получить доступ к некоторым результатам, мы их получаем:
rows = cursor.fetchone()
или же
rows = cursor.fetchmany()
Теперь предположим, что я не извлекаю все строки и решаю выполнить другой запрос, что будет с предыдущими результатами? Их накладные расходы.
Кроме того, следует ли мне создавать курсор для каждой формы команды и как-то постоянно повторно использовать его для тех же команд; Я возглавляю psycopg2, можно как-то оптимизировать команды, которые выполняются много раз, но с разными значениями, как и стоит ли это того?
Спасибо






Предполагая, что вы используете PostgreSQL, курсоры, вероятно, просто реализованы с использованием собственного API курсора базы данных. Вы можете посмотреть исходный код pg8000, чистого модуля Python PostgreSQL DB-API, чтобы увидеть, как он обрабатывает курсоры. Вы также можете посмотреть документация PostgreSQL для курсоров.
Когда вы посмотрите здесь на документация mysqldb, вы увидите, что они реализовали разные стратегии для курсоров. Итак, общий ответ: это зависит от обстоятельств.
Обновлено: вот документация по API mysqldb. Есть некоторая информация о том, как ведет себя каждый тип курсора. Стандартный курсор сохраняет набор результатов в клиенте. Поэтому я предполагаю, что если вы не извлечете все строки результатов, возникнут накладные расходы, потому что даже те строки, которые вы не извлекаете, должны быть переданы клиенту (возможно, по сети). Я предполагаю, что это не сильно отличается от postgresql.
Если вы хотите оптимизировать операторы SQL, которые вы вызываете многократно с множеством значений, вам следует взглянуть на cursor.executemany (). Он подготавливает оператор SQL, поэтому его не нужно анализировать каждый раз, когда вы его вызываете:
cur.executemany('INSERT INTO mytable (col1, col2) VALUES (%s, %s)',
[('val1', 1), ('val2', 2)])
да, я знаю, что ему месяцы: P
Курсор DB-API, похоже, очень похож на курсоры SQL. Это касается управления ресурсами (строками) AFA, DB-API не указывает, должен ли клиент получить все строки или ЗАЯВИТЬ фактический курсор SQL.. Пока интерфейсы fetchXXX делают то, что должны, DB-API доволен.
Это касается курсоров AFA psycopg2 (как вы, возможно, хорошо знаете), «безымянные курсоры DB-API» будут извлекать весь набор результатов - AFAIK, буферизованный в памяти с помощью libpq. «Именованные курсоры DB-API» (концепция psycopg2, которая может быть непереносимой) будет запрашивать строки по запросу (методы fetchXXX).
Как указано в «неизвестном», executemany может использоваться для оптимизации нескольких запусков одной и той же команды. Однако он не учитывает необходимость подготовленных операторов; когда повторное выполнение оператора с разными наборами параметров не является прямым последовательным, executemany () будет работать так же хорошо, как execute (). DB-API «предоставляет» авторам драйверов возможность кэшировать выполненные операторы, но его реализация (какова область действия / время жизни оператора?) Не определена, поэтому невозможно установить ожидания для реализаций DB-API.
Если вы загружаете много данных в PostgreSQL, я настоятельно рекомендую попытаться найти способ использовать COPY.
Re: лучшие практики для курсоров, из FAQ (initd.org/psycopg/docs/faq.html): «Мы предлагаем почти всегда создавать новый курсор и удалять старые, как только данные больше не требуются (вызовите для них close ()). Единственное исключение представляют собой замкнутые циклы, в которых обычно используется один и тот же курсор для целой группы INSERT или UPDATE. "