Django: использование пользовательских необработанных вставок SQL с executemany и MySQL

Мне нужно загрузить много данных в базу данных MySQL. Для большинства моделей я использую ORM django, но одна из моих моделей будет иметь миллиарды (!) экземпляров, и я хотел бы оптимизировать ее операцию вставки.

Кажется, я не могу найти способ заставить работать executemany(), и после поиска в Google кажется, что там почти нет примеров.

Я ищу правильный синтаксис sql + правильный синтаксис команды + правильную структуру данных значений для поддержки команды executemany для следующего оператора sql:

INSERT INTO `some_table` (`int_column1`, `float_column2`, `string_column3`, `datetime_column4`) VALUES (%d, %f, %s, %s)

Да, я явно указываю идентификатор (int_column1) для эффективности.

Короткий пример кода был бы отличным


person Jonathan    schedule 28.11.2010    source источник


Ответы (4)


Вот решение, которое на самом деле использует executemany() !

В основном идея из примера здесь будет работать.

Но обратите внимание, что в Django вам нужно использовать заполнитель %s, а не вопросительный знак.

Кроме того, вы захотите управлять своими транзакциями. Я не буду вдаваться в это здесь, так как есть много доступной документации.

    from django.db import connection,transaction
    cursor = connection.cursor()
    
    
    
    query = ''' INSERT INTO table_name 
            (var1,var2,var3) 
            VALUES (%s,%s,%s) '''
    
    
    query_list = build_query_list() 
    
    # here build_query_list() represents some function to populate
    # the list with multiple records
    # in the tuple format (value1, value2, value3).
    
    
    cursor.executemany(query, query_list)
    
    transaction.commit()

person jsh    schedule 23.05.2011
comment
С опозданием на полгода, но, наконец, ответ относительно executemany(). Я не проверял ваш ответ, но принимаю его и надеюсь, что ваш код работает. - person Jonathan; 24.05.2011
comment
Я нигде не могу найти документацию для функции buildQueryList(). Это часть Джанго? - person Trindaz; 18.08.2011
comment
если вы читаете комментарии... вам решать, как построить эту функцию на основе конкретных потребностей вашего приложения/схемы базы данных... #здесь buildQueryList() представляет некоторую функцию для заполнения #списка несколькими записями #в формате кортежа ( значение1, значение2, значение3). - person jsh; 18.08.2011
comment
Для будущих людей, которые ищут то же самое: фрагмент jsh работает. Спасибо - person Arthur; 23.11.2011
comment
Обратите внимание, что если вы используете MySQLdb 1.2, вы столкнетесь с очень неудачной регрессией производительности. Обходной путь заключается в использовании значений нижнего регистра. Шутки в сторону. См. stackoverflow.com/questions/ 3945642/ - person Paul Du Bois; 27.03.2012
comment
+1 за хороший ответ, но как насчет некоторых pythonic имен переменных и функций? query_list вместо queryList и build_query_list() вместо buildQueryList(). - person MrOodles; 31.05.2012

Вы серьезно предлагаете загружать миллиарды строк (извините, экземпляров) данных через какой-то уровень доступа к данным ORM - как долго у вас есть?

массовая загрузка, если это возможно — http://dev.mysql.com/doc/refman/5.1/en/load-data.html

person Jon Black    schedule 28.11.2010
comment
Я думаю, вы пропустили, где я написал, что я использую ORM для большинства моделей (у которых всего несколько сотен экземпляров) и использую необработанный SQL для одной модели, которая имеет миллиарды экземпляров, но ссылка полезна, спасибо - person Jonathan; 28.11.2010
comment
Кроме того, я не могу использовать данные загрузки, так как я манипулирую данными, прежде чем вводить их в базу данных... - person Jonathan; 28.11.2010
comment
Наконец, да, это важно, даже если для вставки в БД требуется несколько дней. Это одноразовая операция (до следующего раза...) - person Jonathan; 28.11.2010
comment
почему бы вам не написать метод Dump2CSV, который обрабатывает ваши экземпляры и создает серию файлов .dat, которые вы можете загрузить в свою базу данных? - person Jon Black; 29.11.2010
comment
Итак, я предполагаю, что вы говорите, что независимо от того, какова модификация данных, я должен отделить процесс загрузки от части обработки данных и загрузить с помощью load-data - person Jonathan; 30.11.2010
comment
если у вас есть сомнения, возможно, запустите несколько тестов, скажем, с 1 миллионом строк, загруженных через django, и то же самое, используя файл данных загрузки, а затем определите, сколько времени потребуется для загрузки 1000 миллионов строк... - person Jon Black; 01.12.2010
comment
Я провел несколько тестов — разделение предварительной обработки и загрузки почти удвоило время загрузки, так как большая часть времени тратилась на доступ к жесткому диску. - person Jonathan; 24.05.2011

Если вам нужно изменить данные, выполните массовую загрузку с помощью load data во временную таблицу как есть. Затем примените изменения с помощью команды insert into select. IME, это, безусловно, самый быстрый способ получить много данных в таблице.

person nate c    schedule 29.11.2010

Я не знаю, как использовать команду executemany(), но вы можете использовать один оператор SQL INSERT вставить несколько записей

person Jonathan    schedule 04.12.2010