Ранее я работал над проектом PHP, где подготовленные операторы ускоряли запросы SELECT на 20%.
Мне интересно, работает ли это на Python? Кажется, я не могу найти ничего, что конкретно говорит, что это делает или НЕ делает.
Ранее я работал над проектом PHP, где подготовленные операторы ускоряли запросы SELECT на 20%.
Мне интересно, работает ли это на Python? Кажется, я не могу найти ничего, что конкретно говорит, что это делает или НЕ делает.
Прямой ответ: нет.
ответ Джошперри является хорошим объяснением того, что он делает вместо этого.
Из eugene y ответ на аналогичный вопрос,
Проверьте Комментарии к пакету MySQLdb:
«Параметризация» выполняется в MySQLdb путем экранирования строк, а затем слепой интерполяции их в запрос вместо использования API MYSQL_STMT. В результате строки Unicode должны пройти через два промежуточных представления (закодированная строка, экранированная закодированная строка), прежде чем они будут получены базой данных.
Так что ответ таков: нет, это не так.
Большинство языков предоставляют способ делать общие параметризованные операторы, Python ничем не отличается. Когда используется параметризованный запрос, базы данных, поддерживающие подготовку операторов, делают это автоматически.
В python параметризованный запрос выглядит так:
cursor.execute("SELECT FROM tablename WHERE fieldname = %s", [value])
Конкретный стиль параметризации может отличаться в зависимости от вашего драйвера, вы можете импортировать свой модуль db, а затем выполнить print yourmodule.paramstyle
.
Из PEP-249:
парамстиль
String constant stating the type of parameter marker formatting expected by the interface. Possible values are [2]: 'qmark' Question mark style, e.g. '...WHERE name=?' 'numeric' Numeric, positional style, e.g. '...WHERE name=:1' 'named' Named style, e.g. '...WHERE name=:name' 'format' ANSI C printf format codes, e.g. '...WHERE name=%s' 'pyformat' Python extended format codes, e.g. '...WHERE name=%(name)s'
execute
внутри executemany
), тогда как oursql отправляет prepare
, за которым следует execute
(или executemany
, который только отправляет параметры/значения). launchpad.net/oursql
- person type; 26.03.2013
mysql.connector.paramstyle == 'pyformat'
но Подготовленные операторы.. .. может использовать стиль форматирования (%s) или qmark (?). Это отличается от неподготовленных операторов... которые могут использовать стиль параметризации формата или pyformat. Таким образом, очевидно, что неподготовленные операторы более надежны, поскольку они допускают замены %(named)s.
- person Bob Stein; 20.09.2015
После беглого просмотра метода execute() объекта Cursor пакета MySQLdb (полагаю, что-то вроде пакета де-факто для интеграции с mysql) кажется, что (по крайней мере, по умолчанию) он выполняет только интерполяцию строк. и цитирование, а не фактический параметризованный запрос:
if args is not None:
query = query % db.literal(args)
Если это не интерполяция строк, то что?
В случае executemany он фактически пытается выполнить вставку/замену как один оператор, а не выполнять его в цикле. Вот и все, никакой магии там, кажется. По крайней мере, не в его поведении по умолчанию.
РЕДАКТИРОВАТЬ: О, я только что понял, что оператор по модулю может быть переопределен, но мне захотелось обмануть и найти источник. Однако нигде не нашел переопределенного mod
.
Для тех, кто просто пытается понять это, ДА вы можете использовать подготовленные операторы с Python и MySQL. Просто используйте MySQL Connector/Python из самой MySQL и создайте правильный курсор:
https://dev.mysql.com/doc/connector-python/en/index.html
https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.html
cursor = connection.cursor(); cursor.execute("SELECT * FROM t WHERE name = %(name)s", dict(name='Monty'))
- person Bob Stein; 20.09.2015
Использование интерфейса SQL, предложенное Амитом, может работать, если вас интересует только производительность. Однако при этом вы теряете защиту от SQL-инъекций, которую могла бы обеспечить встроенная поддержка Python для подготовленных операторов. В Python 3 есть модули, обеспечивающие поддержку подготовленных операторов для PostgreSQL. Для MySQL «oursql», по-видимому, обеспечивает настоящую поддержку подготовленных операторов (а не подделку, как в других модулях).
Не имеет прямого отношения, но этот ответ на другой вопрос at SO включает сведения о синтаксисе "шаблонных" запросов. Я бы сказал, что автоматическое экранирование будет их самой важной особенностью...
Что касается производительности, обратите внимание на метод executemany
для объектов курсора. Он объединяет несколько запросов и выполняет их все за один раз, что действительно приводит к повышению производительности.
insert into foo (f1,f2,f3) values (f11,f12,f13),(f21,f22,f23),...
и так далее (вместо того, чтобы вы выполняли эти вставки в цикле). Я не говорю, что это не увеличивает производительность.
- person shylent; 22.12.2009
.executemany()
зацикливается только на .execute()
- person type; 26.03.2013
Есть решение!
Вы можете использовать их, если поместите их в хранимую процедуру на сервере и вызовете их так из python...
cursor.callproc(Procedurename, args)
Вот хороший небольшой учебник по хранимым процедурам в mysql и python.
http://www.mysqltutorial.org/calling-mysql-stored-procedures-python/