Я выполнял итерацию по запросу в SQLAlchemy и выполнял обновления в строках, и я испытывал неожиданно низкую производительность, на несколько порядков медленнее, чем я ожидал. База данных содержит около 12 тыс. Строк. Мой первоначальный запрос и цикл выглядит следующим образом:Понимание производительности SQLAlchemy при итерации по истекшему запросу и обновлению
query_all = session.query(MasterImages).all()
for record_counter, record in enumerate(query_all):
# Some stuff happens here, set_id and set_index are defined
session.query(MasterImages).\
filter(MasterImages.id == record.id).\
update({'set_id':set_id, 'set_index':set_index})
if record_counter % 100 == 0:
session.commit()
print 'Updated {:,} records'.format(record_counter)
session.commit()
Первая итерация цикла была очень быстро, но тогда это казалось бы, остановится после первой фиксации. Я попробовал кучу разных подходов, но ничего не получал. Затем я попытался изменить мой запрос так только выбранные поля I, необходимые для расчета значения по set_id
и set_index
я использую в своем обновлении, как это:
query_all = session.query(MasterImages.id, MasterImages.project_id,
MasterImages.visit, MasterImages.orbit,
MasterImages.drz_mode, MasterImages.cr_mode).all()
Это произвело исполнение я ожидал, пахоты через все записи в течение минуты. Подумав об этом некоторое время, я думаю, что моя проблема заключалась в том, что в моем первом запросе после коммита он превратился в устаревший запрос, потому что я обновил поле, которое было (необязательно) в запросе, который я повторял. Это, я думаю, вынудило Алхиму регенерировать запрос после каждой фиксации. Удалив поля, которые я обновлял из запроса, который я выполнял, я думаю, что смог использовать один и тот же запрос, и это привело к увеличению моей производительности.
Правильно ли я?
Так что 'expire_on_commit' является дополнительной оптимизацией, которую я мог бы сделать? Какова наилучшая практика того, когда и когда не использовать это? Кроме того, могу ли я исправить свое понимание старых запросов в моем исходном сообщении? – ACV
Вид. SQLAlchemy отмечает все объекты в 'query_all' как истекшие (или« устаревшие », как вы выразились) после' .commit() ', а не после' .update() '. То, что истекает, означает, что при следующем попытке доступа к атрибуту на вашем объекте SQLAlchemy выдает 'SELECT' для обновления объекта. Отключение 'expire_on_commit' не позволит этому сделать это. 'expire_on_commit' - это опция, так что наивное использование ORM не нарушается, поэтому, если вы знаете, что делаете, вы можете спокойно отключить его. – univerio
Я обновил вопрос, чтобы использовать соответствующий термин «expired» вместо «stale». Но вы можете объяснить, почему мой код ускорился, когда я изменяю запрос, который я повторял? – ACV