Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 5, 2015 17:41:44

Constverum
Зарегистрирован: 2015-08-03
Сообщения: 2
Репутация: +  0  -
Профиль   Отправить e-mail  

Массовый update

Для PostgreSQL:

params = defaultdict(list)
for item in goods:
    params['names'].append(item.name)
    params['date_a'].append(item.date1)
    params['date_b'].append(item.date2)
    params['date_c'].append(item.date3)
    params['text_a'].append(item.text1)
    params['text_b'].append(item.text2)
    params['text_c'].append(item.text3)
    params['integer_a'].append(item.integer)
    params['ids'].append(item.id)
    
cursor = connection.cursor()
cursor.execute('''UPDATE tbl
    SET
      "name" = item.name,
      "date1" = item.date_a,
      "date2" = item.date_b,
      "date3" = item.date_c,
      "text1" = item.text_a,
      "text2" = item.text_b,
      "text3" = item.text_c,
      "integer" = item.integer_a
    FROM (select
      unnest(%(names)s) AS price,
      unnest(%(date_a)s) AS date_a,
      unnest(%(date_b)s) AS date_b,
      unnest(%(date_c)s) AS date_c,
      unnest(%(text_a)s) AS text_a,
      unnest(%(text_b)s) AS text_b,
      unnest(%(text_c)s) AS text_c,
      unnest(%(integer_a)s) AS integer_a,
      unnest(%(ids)s) AS _id) AS item
    WHERE
      tbl."id" = item._id;''', params)

neitro
Мне нужно обновить 10к строк.
Попытки через алхимию и sqlite3 выполняются очень долго ~ 5-10 часов.
Встал вопрос, как это исправить, как ускорить этот процесс, т.е. сделать массовый update.

Без индексов с доп. условиями на слабой машинке обновляет порядка 10k строк за ~1 сек (да, лучше обновлять пачками по несколько тысяч). На 10kk уйдет ~15-16 минут (у вас может быстрее).

Офлайн

#2 Авг. 6, 2015 09:10:51

neitro
Зарегистрирован: 2015-03-13
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Массовый update

Собсвенно индекс решил задачу со скоростью работы - выполняется несколько секунд, база разрослась на 25%. Что не критично.

4kpt_III
Получать порциями и обновлять, если нужно. Для этого есть in_ в алхимии.

Ну в случае фильтра - все понятно
session.query(Info).filter(Info.name.in_(__массив значений__))
А вот, как апнуть через in_ я в мануале не нашел…
сейчас делаю так на каждом шаге
con.execute('sql запрос')
раз в n шагов
con.commit()

PS след шагом будет переход на postgreSql. Всем спасибо за проявленную активность)



Офлайн

#3 Авг. 6, 2015 12:14:01

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Массовый update

neitro
А вот, как апнуть через in_ я в мануале не нашел…

Предполагалось сначала получить, а потом уже обновлять, если надо. Обновляется легко. Просто назначаете новые атрибуты и commit().
Ну и update никто не отменял. Но все равно, я за проверку необходимости обновления вместо массового обновления.

Отредактировано 4kpt_III (Авг. 6, 2015 12:14:52)

Офлайн

#4 Авг. 6, 2015 15:47:53

neitro
Зарегистрирован: 2015-03-13
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Массовый update

4kpt_III
Предполагалось сначала получить, а потом уже обновлять, если надо. Обновляется легко. Просто назначаете новые атрибуты и commit().
Ну и update никто не отменял. Но все равно, я за проверку необходимости обновления вместо массового обновления.
Нужно Обновлять по 1 записи или есть возможность массовой замены аналогично executemany в библиотеке sqlite3 в алхимии.

PS обновлять все строки нужно будет - причина проста - 1-н из параметров - это дата проверки строки на актуальность. А вообщем и целом я с вами согласен.

Офлайн

#5 Авг. 6, 2015 15:58:23

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Массовый update

Получили 100 записей. Обновили их по-полям. Потому сделали .commit(). 100 записей обновлятся в БД.

P.S. Если есть данные, которые требуют обновления только 1 поля и только того, которое ставится на автомате, то можно просто прикрутить event. Тогда во всех полях автоматом будет это поле изменяться при commit'e, при этом ручками ничего делать не нужно будет.

Отредактировано 4kpt_III (Авг. 6, 2015 19:45:05)

Офлайн

#6 Авг. 6, 2015 16:00:23

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Массовый update

Мало того, возникает вопрос, что делать с записями, которых еще или уже нет в обновляемой базе? Их же нужно удалять или добавлять.

P.S. Ну и не проще ли одну базу вынести на внешний сервис. Чтобы к ней все “друзья-товарищи” подключались?

Отредактировано 4kpt_III (Авг. 6, 2015 16:06:52)

Офлайн

#7 Авг. 7, 2015 00:16:29

neitro
Зарегистрирован: 2015-03-13
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Массовый update

4kpt_III
Мало того, возникает вопрос, что делать с записями, которых еще или уже нет в обновляемой базе? Их же нужно удалять или добавлять.
Такой ситуации не возникнет.
+ в скрипте у меня все через try идет - если что ничего критичного не произойдет.

4kpt_III
P.S. Ну и не проще ли одну базу вынести на внешний сервис. Чтобы к ней все “друзья-товарищи” подключались?

До уровня вынести базу на внешний сервис я еще не дошел.
Я еще вожусь с PostgreSQL (не работал с ней до - читаю маны по-тихоньку). Потом прикрутить flask еще собираюсь, потом прикрутить ngnix и выставить базу в режиме доступности. В виде api.

Офлайн

#8 Авг. 7, 2015 01:25:23

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Массовый update

neitro
Посмотрел стек. Вы на правильном пути.

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version