Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Базы данных
  • » sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке [RSS Feed]

#1 Авг. 29, 2013 19:03:27

kosolapovdg
Зарегистрирован: 2013-05-11
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

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

Код, который воспроизводит проблему:

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

Офлайн

#2 Авг. 29, 2013 19:48:14

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

А так:

# ...
b = default_session.query(BarLog)[:3]
for bar in b:
# ...



Офлайн

#3 Авг. 30, 2013 10:43:47

kosolapovdg
Зарегистрирован: 2013-05-11
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

Lexander
А так:
# …
b = default_session.query(BarLog)
for bar in b:
# …

То же самое

Офлайн

#4 Авг. 30, 2013 11:55:23

bismigalis
Зарегистрирован: 2010-10-02
Сообщения: 449
Репутация: +  47  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

коммитить наверное надо один раз после цикла

Офлайн

#5 Авг. 30, 2013 17:45:01

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

Lexander, может имели ввиду следующее:

# ...
b = list(default_session.query(BarLog)[:3])
for bar in b:
# ...

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

upd: slice и так не ленивый список возвращает.

Отредактировано reclosedev (Авг. 30, 2013 18:06:39)

Офлайн

#6 Авг. 30, 2013 18:25:04

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

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

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

Ппример на SO с expunge() для похожего случая.

Офлайн

#7 Авг. 31, 2013 09:10:58

kosolapovdg
Зарегистрирован: 2013-05-11
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке

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

Ответ на мой вопрос в английском форуме

Офлайн

  • Начало
  • » Базы данных
  • » sqlalchemy в запросе на выборку создает кучу подзапросов при выборке-вставке[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version