Проблемы с массовым обновлением sqlalchemy

Мне нужно периодически увеличивать значения в столбце с данными, которые я получаю в файле. Таблица имеет > 400000 строк. Пока все мои попытки приводят к очень низкой производительности. Я написал эксперимент, который отражает мои требования:

#create table
engine = create_engine('sqlite:///bulk_update.db', echo=False)
metadata = MetaData()

sometable = Table('sometable',  metadata,
    Column('id', Integer, Sequence('sometable_id_seq'), primary_key=True),
    Column('column1', Integer),
    Column('column2', Integer),
)

sometable.create(engine, checkfirst=True)

#initial population
conn = engine.connect()
nr_of_rows = 50000
insert_data = [ { 'column1': i, 'column2' : 0 } for i in range(1, nr_of_rows)]
result = conn.execute(sometable.insert(), insert_data)

#update
update_data = [ {'col1' : i, '_increment': randint(1, 500)} for i in range(1, nr_of_rows)]

print "nr_of_rows", nr_of_rows
print "start time   : " + str(datetime.time(datetime.now()))

stmt = sometable.update().\
        where(sometable.c.column1 == bindparam('col1')).\
        values({sometable.c.column2 : sometable.c.column2 +     bindparam('_increment')})

conn.execute(stmt, update_data)

print "end time : " + str(datetime.time(datetime.now()))

Я получаю следующие значения:

nr_of_rows 10000
start time  : 10:29:01.753938
end time    : 10:29:16.247651

nr_of_rows 50000
start time  : 10:30:35.236852
end time    : 10:36:39.070423

поэтому количество строк в 400000+ займет слишком много времени.

Я новичок в sqlalchemy, но я делал много чтения документов, и я просто не могу понять, что я делаю неправильно.

заблаговременно!

Ответы

Ответ 1

Вы используете правильный подход, делая массовое обновление с помощью одного запроса.

Причина, по которой это так долго, объясняется тем, что таблица не имеет индекса на sometable.column1. Он имеет только первичный индекс в столбце id.

В запросе на обновление используется sometable.column1 в предложении where для идентификации записи. Таким образом, база данных должна проверять все записи таблицы для каждого обновления столбца.

Чтобы ускорить выполнение обновления, вам необходимо обновить код определения схемы таблицы, чтобы добавить создание индекса в определение столбца с помощью , index=True:

sometable = Table('sometable',  metadata,
    Column('id', Integer, Sequence('sometable_id_seq'), primary_key=True),
    Column('column1', Integer, index=True),
    Column('column2', Integer),
)

Я протестировал обновленный код на моей машине - потребовалось 2 секунды для запуска программы.

BTW kudos к вашему описанию вопроса - вы помещаете весь код, необходимый для воспроизведения вашей проблемы.