Попытки вставки в цикле обычным insert привело к тому что 10 тыс. записей вставлялось примерно минут 15.
В общем правильный путь вставки за несколько секунд полного прайса оказался следующим.
sqlalchemy:
- class Price(base):
- __tablename__ = 'prices'
- ....
- s = session()
- buffer = []
- for item in items:
- ...
- buffer.append({'name':.., 'price':...})
- s.bulk_insert_mappings(Price, buffer)
- s.commit()
Так подсказывают делать все примеры и это правильно. Должен по идее выполниться pymysql.cursor.executemany(). Но как оказалось в последней версии pymysql есть ошибка, executemany не распознает конструкцию INSERT ... VALUES (%(name)s, %(price)s) и делает в цикле запрос на каждую запись, т.е. получаем те же тормоза.
После небольшого патча pymysql все встает на свои места.
Готовую версию можно взять так
- #!/bin/bash
- git clone https://github.com/WorldException/PyMySQL.git
- pip uninstall pymysql
- cd PyMySQL
- python setup.py install
Патч выглядит так
pymysql/cursor.py -RE_INSERT_VALUES = re.compile(r"""(INSERT\s.+\sVALUES\s+)(\(\s*%s\s*(?:,\s*%s\s*)*\))(\s*(?:ON DUPLICATE.*)?)\Z""", +RE_INSERT_VALUES = re.compile(r"""(INSERT\s.+\sVALUES\s+)(\(\s*(?:%s|%\(.+\)s)\s*(?:,\s*(?:%s|%\(.+\)s)\s*)*\))(\s*(?:ON DUPLICATE.*)?)\Z""", |
ВНИМАНИЕ!
Мой патч приняли в основную ветку PyMySQL начиная с версии 0.7.2, так что вам достаточно обновиться!
Еще важный момент настройки MySQL который позволил мне избежать постоянных deadlock при параллельной вставке и ускорить вставку на порядок. Это разбивка таблицы на партиции по ключу, в моем случае это было имя прайса. Выглядит это примерно так:
PARTITION BY KEY (unikey) PARTITIONS 100
А так же
DELAY_KEY_WRITE=1
Комментариев нет:
Отправить комментарий