2012-06-15 2 views
2

Я пытаюсь сохранить некоторые данные, сгенерированные скриптом python в базе данных MySQL. По существу, я использую следующие команды:oursql очень медленно вставляет данные

con = oursql.connect(user="user", host="host", passwd="passwd", 
        db="testdb") 
c = con.cursor()        

c.executemany(insertsimoutput, zippedsimoutput) 

con.commit() 
c.close() 

где

insertsimoutput = '''insert into simoutput 
         (repnum, 
         timepd, 
         ...) values (?, ?, ...?)''' 

около 30 000 строк вставляются и около 15 столбцов. Вышеуказанное занимает около 7 минут. Если я использую MySQLdb вместо oursql, это занимает около 2 секунд. Почему эта огромная разница? Предполагается ли это, что это сделано другим способом в нашей книге, наш oursql просто медленный? Если есть лучший способ вставить эти данные с помощью oursql, я был бы признателен, если бы вы могли сообщить мне об этом.

спасибо.

+0

Вы посмотрели на запрос, который делает oursql? –

+0

@Simeon Я не уверен, как это найти. Не могли бы вы объяснить? – Curious2learn

+1

Вы можете посмотреть в журналах сервера mysql (https://dev.mysql.com/doc/refman/5.1/en/server-logs.html). Из разницы во времени, которую вы наблюдаете, я бы предположил, что oursqls executemany делает 30k однострочных вставок, а MySQLdb вставляет сразу несколько строк. – l4mpi

ответ

1

Я бы сказал, чтобы проверить, поддерживает ли oursql команду sql bulk insert, чтобы повысить производительность.

+0

Я ничего не нашел о 'bulk insert' в своей документации. Благодаря! – Curious2learn

-1

Oursql действительно поддерживает bulk insert заявления. Я написал код для этого, используя оболочку sqlalchemy.

Для чистого oursql, что-то, как это должно быть в порядке:

with open('tmp.csv', 'wb') as tmp: 
    for item in zippedsimoutput: 
     tmp.write("{0}\n".format(item)) 
c.execute("""LOAD DATA LOCAL INFILE 'tmp.csv' INTO TABLE flags FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n' ;""") 

Обратите внимание, что строки должны быть в том же порядке, как и столбцы в базе данных.

+0

демпинг в csv, а затем загрузка не похожа на то, что @ Curious2learn хочет ... – underrun

+0

@underrun Это было пару лет, но IIRC это был единственный способ, которым нашsql поддерживал создание «объемной вставки». Поскольку он искал быстрый способ вставки большого набора данных, демонстрация синтаксиса объемной вставки казалась наиболее полезной. Опять же, IIRC, oursql * не поддерживает многократную вставку, поэтому orm не преобразовывает запрос, но запускает его много раз с каждым элементом. Поскольку нет многострочной вставки, единственной опцией остается объемная вставка. Это не проблема для базовой базы данных MySQL, но это не вопрос. –

6

Разница заключается в том, что MySQLdb делает некоторые повозка, запряженная волами на ваш запрос, пока oursql не ...

Принимая это:

cursor.executemany("INSERT INTO sometable VALUES (%s, %s, %s)", 
    [[1,2,3],[4,5,6],[7,8,9]]) 

MySQLdb переводит его перед запуском в это:

cursor.execute("INSERT INTO sometable VALUES (1,2,3),(4,5,6),(7,8,9)") 

Но если вы это сделаете:

cursor.executemany("INSERT INTO sometable VALUES (?, ?, ?)", 
    [[1,2,3],[4,5,6],[7,8,9]]) 

В oursql, он переводится в нечто вроде этого псевдокода:

stmt = prepare("INSERT INTO sometable VALUES (?, ?, ?)") 
for params in [[1,2,3],[4,5,6],[7,8,9]]: 
    stmt.execute(*params) 

Так что, если вы хотите эмулировать, что MySQLdb делает, но выгоду от подготовленных заявлений и других благости с oursql, что вам нужно сделать это:

from itertools import chain 
data = [[1,2,3],[4,5,6],[7,8,9]] 
one_val = "({})".format(','.join("?" for i in data[0])) 
vals_clause = ','.join(one_val for i in data) 
cursor.execute("INSERT INTO sometable VALUES {}".format(vals_clause), 
    chain.from_iterable(data)) 

Держу пари oursql будет быстрее, если вы сделаете это :-)

Кроме того, если вы думаете, что его уродливым, вы правы. Но просто помните, что MySQL db делает что-то более уродливое внутри - его используют регулярные выражения для анализа вашего оператора INSERT и прерывания параметризованной части, а THEN делает то, что я предложил вам для oursql.

Смежные вопросы