Я запускаю новое приложение и ищу возможность использования ORM - в частности, SQLAlchemy.
Скажем, у меня в базе данных есть столбец foo, и я хочу увеличить его. В прямом sqlite это просто:
db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')
Я выяснил эквивалент SQLAlchemy SQL-builder:
engine = sqlalchemy.create_engine('sqlite:///mydata.sqlitedb')
md = sqlalchemy.MetaData(engine)
table = sqlalchemy.Table('stuff', md, autoload=True)
upd = table.update(values={table.c.foo:table.c.foo+1})
engine.execute(upd)
Это немного медленнее, но в этом немного.
Вот мое лучшее предположение о подходе SQLAlchemy ORM:
# snip definition of Stuff class made using declarative_base
# snip creation of session object
for c in session.query(Stuff):
c.foo = c.foo + 1
session.flush()
session.commit()
Это работает правильно, но это занимает чуть менее пятидесяти раз больше, чем подходят два других. Я предполагаю, что это потому, что он должен занести все данные в память, прежде чем он сможет с ними работать.
Есть ли способ сгенерировать эффективный SQL с помощью ORM SQLAlchemy? Или с помощью любого другого ORM на Python? Или мне просто вернуться к написанию SQL вручную?
python
orm
sqlalchemy
Джон Фухи
источник
источник
Ответы:
ORM SQLAlchemy предназначен для использования вместе со слоем SQL, а не для его скрытия. Но при использовании ORM и простого SQL в одной транзакции необходимо помнить об одном или двух моментах. По сути, с одной стороны, изменения данных ORM попадут в базу данных только тогда, когда вы сбросите изменения из своего сеанса. С другой стороны, операторы обработки данных SQL не влияют на объекты, находящиеся в вашем сеансе.
Итак, если вы скажете
он будет делать то, что он говорит, извлекать все объекты из базы данных, изменять все объекты, а затем, когда пришло время сбросить изменения в базу данных, обновлять строки одну за другой.
Вместо этого вы должны сделать это:
Это будет выполняться как один запрос, как и следовало ожидать, и поскольку по крайней мере в конфигурации сеанса по умолчанию истекает срок действия всех данных в сеансе при фиксации, у вас нет проблем с устаревшими данными.
В почти выпущенной серии 0.5 вы также можете использовать этот метод для обновления:
Это в основном запустит тот же оператор SQL, что и предыдущий фрагмент, но также выберет измененные строки и истечет срок хранения любых устаревших данных в сеансе. Если вы знаете, что не используете какие-либо данные сеанса после обновления, вы также можете добавить
synchronize_session=False
в оператор обновления и избавиться от этого выбора.источник
Попробуй это =)
источник
json
столбецЕсть несколько способов ОБНОВЛЕНИЯ с помощью sqlalchemy
источник
Вот пример того, как решить ту же проблему без необходимости вручную отображать поля:
Итак, чтобы обновить экземпляр Media, вы можете сделать что-то вроде этого:
источник
Без тестирования я бы попробовал:
(IIRC, commit () работает без flush ()).
Я обнаружил, что иногда выполнение большого запроса с последующим повторением в Python может быть на 2 порядка быстрее, чем множество запросов. Я предполагаю, что итерация по объекту запроса менее эффективна, чем итерация по списку, сгенерированному методом all () объекта запроса.
[Обратите внимание на комментарий ниже - это совсем не ускорило процесс].
источник
Если это связано с накладными расходами на создание объектов, то, вероятно, это вообще невозможно ускорить с помощью SA.
Если это связано с загрузкой связанных объектов, возможно, вы сможете что-то сделать с ленивой загрузкой. Много ли объектов создается по ссылкам? (IE, получение объекта Company также получает все связанные объекты People).
источник