Найти - Пользователи
Полная версия: sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке
Начало » Базы данных » sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке
1
kosolapovdg
Добрый вечер. Проблема такая: есть цикл перебора значений. Внутри этого цикла нужно вставлять строки в базу данных. Проблема в том, что после первой вставки в другую таблицу, появляется куча запросов на выборку данных. Как избежать при таком подходе кучу лишних запросов в базу данных

Код, который воспроизводит проблему:
engine = create_engine(connect_str, echo=True)
Session = sessionmaker(bind=engine)
for bar in default_session.query(BarLog)[:3]:
    conf = ManagerConfig(indicator_config='', timeframe=bar.timeframe, paper_no=1)
    default_session.add(conf)
    default_session.commit()
    if number == 4:
        break

лог sqlalchemy
2013-08-29 22:52:58,640 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2013-08-29 22:52:58,642 INFO sqlalchemy.engine.base.Engine SELECT bar_log.id AS bar_log_id, bar_log.max AS bar_log_max, bar_log.min AS bar_log_min, bar_log.open AS bar_log_open, bar_log.close AS bar_log_close, bar_log.volume AS bar_log_volume, bar_log.time_start AS bar_log_time_start, bar_log.date AS bar_log_date, bar_log.timeframe AS bar_log_timeframe, bar_log.paper_no AS bar_log_paper_no
FROM bar_log
LIMIT %(param_1)s
2013-08-29 22:52:58,642 INFO sqlalchemy.engine.base.Engine {'param_1': 3}
2013-08-29 22:52:58,646 INFO sqlalchemy.engine.base.Engine INSERT INTO manager_config (paper_no, timeframe, indicator_config) VALUES (%(paper_no)s, %(timeframe)s, %(indicator_config)s) RETURNING manager_config.id
2013-08-29 22:52:58,646 INFO sqlalchemy.engine.base.Engine {'indicator_config': ‘', ’paper_no': 1, ‘timeframe’: 1}
2013-08-29 22:52:58,647 INFO sqlalchemy.engine.base.Engine COMMIT
2013-08-29 22:52:58,662 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2013-08-29 22:52:58,664 INFO sqlalchemy.engine.base.Engine SELECT bar_log.id AS bar_log_id, bar_log.max AS bar_log_max, bar_log.min AS bar_log_min, bar_log.open AS bar_log_open, bar_log.close AS bar_log_close, bar_log.volume AS bar_log_volume, bar_log.time_start AS bar_log_time_start, bar_log.date AS bar_log_date, bar_log.timeframe AS bar_log_timeframe, bar_log.paper_no AS bar_log_paper_no
FROM bar_log
WHERE bar_log.id = %(param_1)s
2013-08-29 22:52:58,664 INFO sqlalchemy.engine.base.Engine {'param_1': 2}
2013-08-29 22:52:58,667 INFO sqlalchemy.engine.base.Engine INSERT INTO manager_config (paper_no, timeframe, indicator_config) VALUES (%(paper_no)s, %(timeframe)s, %(indicator_config)s) RETURNING manager_config.id
2013-08-29 22:52:58,668 INFO sqlalchemy.engine.base.Engine {'indicator_config': ‘', ’paper_no': 1, ‘timeframe’: 1}
2013-08-29 22:52:58,670 INFO sqlalchemy.engine.base.Engine COMMIT
2013-08-29 22:52:58,679 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2013-08-29 22:52:58,681 INFO sqlalchemy.engine.base.Engine SELECT bar_log.id AS bar_log_id, bar_log.max AS bar_log_max, bar_log.min AS bar_log_min, bar_log.open AS bar_log_open, bar_log.close AS bar_log_close, bar_log.volume AS bar_log_volume, bar_log.time_start AS bar_log_time_start, bar_log.date AS bar_log_date, bar_log.timeframe AS bar_log_timeframe, bar_log.paper_no AS bar_log_paper_no
FROM bar_log
WHERE bar_log.id = %(param_1)s
2013-08-29 22:52:58,681 INFO sqlalchemy.engine.base.Engine {'param_1': 3}
2013-08-29 22:52:58,685 INFO sqlalchemy.engine.base.Engine INSERT INTO manager_config (paper_no, timeframe, indicator_config) VALUES (%(paper_no)s, %(timeframe)s, %(indicator_config)s) RETURNING manager_config.id
2013-08-29 22:52:58,685 INFO sqlalchemy.engine.base.Engine {'indicator_config': ‘', ’paper_no': 1, ‘timeframe’: 1}
2013-08-29 22:52:58,688 INFO sqlalchemy.engine.base.Engine COMMIT
Lexander
А так:
# ...
b = default_session.query(BarLog)[:3]
for bar in b:
# ...
kosolapovdg
Lexander
А так:
# …
b = default_session.query(BarLog)
for bar in b:
# …

То же самое
bismigalis
коммитить наверное надо один раз после цикла
reclosedev
Lexander, может имели ввиду следующее:
# ...
b = list(default_session.query(BarLog)[:3])
for bar in b:
# ...

я бы так попробовал.

upd: slice и так не ленивый список возвращает.
reclosedev
Получается, что при commit() вызывается Session.expire_all() и при доступе к атрибутам объектов, выполняется запрос. Должен помочь совет bismigalis, плюс это должно работать быстрее.

Еще есть вариант использовать возможность отсоединять объекты от сессии
session.expunge(bar) или
session.expunge_all()

Ппример на SO с expunge() для похожего случая.
kosolapovdg
Спасибо за ответы. Мне в английской группе объяснили, что после того, как делаем commit(), все объекты sqlalchemy “протухают”. Именно поэтому sqlalchemy после первого коммита лезет в базу данных, чтобы достать актуальные данные.
Для отключения такого поведения, нужно в sessionmaker передавать параметр expire_on_commit=False.

Ответ на мой вопрос в английском форуме
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB