我有我想要插入到Oracle数据库表中的一些月度天气数据,但我想插入一个批次相应的记录,以便更有效。 任何人都可以提出建议,我怎么会去约在Python这样做呢?
例如,让我们说我的表有四个字段:站号,日期和两个值的字段。 该记录由站ID和日期字段(复合键)唯一地标识。 我必须插入每个站的值将保持在满年的数据X数的列表,因此,例如,如果有两个年值,则值列表将包含24个值。
我认为下面是我应该这样做,如果我想插入记录一次一个方式:
connection_string = "scott/tiger@testdb"
connection = cx_Oracle.Connection(connection_string)
cursor = cx_Oracle.Cursor(connection)
station_id = 'STATION_1'
start_year = 2000
temps = [ 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3 ]
precips = [ 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8 ]
number_of_years = len(temps) / 12
for i in range(number_of_years):
for j in range(12):
# make a date for the first day of the month
date_value = datetime.date(start_year + i, j + 1, 1)
index = (i * 12) + j
sql_insert = 'insert into my_table (id, date_column, temp, precip) values (%s, %s, %s, %s)', (station_id, date_value, temps[index], precips[index]))
cursor.execute(sql_insert)
connection.commit()
有没有办法做我正在做的事情上面,但,为了提高效率,进行批量插入的方法吗? 顺便说一句我的经验与Java / JDBC / Hibernate的,所以如果有人能给出一个解释/例子进行比较的Java方法,然后它会是特别有帮助。
编辑:也许我需要使用cursor.executemany()所描述的在这里 ?
在此先感谢您的任何建议,意见等。
Answer 1:
下面是我想出这似乎很好地工作(但请评论,如果有改善此问题的方法):
# build rows for each date and add to a list of rows we'll use to insert as a batch
rows = []
numberOfYears = endYear - startYear + 1
for i in range(numberOfYears):
for j in range(12):
# make a date for the first day of the month
dateValue = datetime.date(startYear + i, j + 1, 1)
index = (i * 12) + j
row = (stationId, dateValue, temps[index], precips[index])
rows.append(row)
# insert all of the rows as a batch and commit
ip = '192.1.2.3'
port = 1521
SID = 'my_sid'
dsn = cx_Oracle.makedsn(ip, port, SID)
connection = cx_Oracle.connect('username', 'password', dsn)
cursor = cx_Oracle.Cursor(connection)
cursor.prepare('insert into ' + database_table_name + ' (id, record_date, temp, precip) values (:1, :2, :3, :4)')
cursor.executemany(None, rows)
connection.commit()
cursor.close()
connection.close()
Answer 2:
使用Cursor.prepare()
和Cursor.executemany()
从cx_Oracle文档 :
Cursor.prepare
( 语句 [, 标签 ])
这可以在通话之前被用来执行()来定义将要执行的语句。 当做到这一点,在准备阶段将不被当调用执行进行()与无或相同的字符串对象的发言中。 [...]
Cursor.executemany
( 声明 参数 )
准备语句用于对数据库执行,然后执行它针对序列参数中找到的所有参数映射或序列。 该声明被以同样的方式管理的execute()方法对其进行管理。
因此,使用上述两个函数,你的代码就变成了:
connection_string = "scott/tiger@testdb"
connection = cx_Oracle.Connection(connection_string)
cursor = cx_Oracle.Cursor(connection)
station_id = 'STATION_1'
start_year = 2000
temps = [ 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3 ]
precips = [ 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8 ]
number_of_years = len(temps) / 12
# list comprehension of dates for the first day of the month
date_values = [datetime.date(start_year + i, j + 1, 1) for i in range(number_of_years) for j in range(12)]
# second argument to executemany() should be of the form:
# [{'1': value_a1, '2': value_a2}, {'1': value_b1, '2': value_b2}]
dict_sequence = [{'1': date_values[i], '2': temps[i], '3': precips[i]} for i in range(1, len(temps))]
sql_insert = 'insert into my_table (id, date_column, temp, precip) values (%s, :1, :2, :3)', station_id)
cursor.prepare(sql_insert)
cursor.executemany(None, dict_sequence)
connection.commit()
另请参阅Oracle的精通Oracle + Python的系列文章。
Answer 3:
我会创建一个使用联盟的大SQL插入语句:
insert into mytable(col1, col2, col3)
select a, b, c from dual union
select d, e, f from dual union
select g, h, i from dual
你可以建立在Python中的字符串,并给它Oracle作为一个语句来执行。
Answer 4:
作为一个评论说,考虑使用INSERT ALL
。 据说这将是比使用显著快executemany()
例如:
INSERT ALL
INTO mytable (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
INTO mytable (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
INTO mytable (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
SELECT * FROM dual;
http://www.techonthenet.com/oracle/questions/insert_rows.php
Answer 5:
仅供参考我的测试结果:
我插入5000行。 每行3列。
- 插入运行5000次,它的成本1.24分钟。
- 与executemany运行,它的成本0.125秒。
- 用插入运行的所有代码:它的成本4.08分钟。
Python代码中,SQL状插入所有成T(A,B,C)选择哪个设置:1,:2,:3从双UNION ALL选择:4,:5:6从道尔·...
在Python代码设置此长SQL,它的成本0.145329秒。
我测试一个非常古老的太阳机器上我的代码。 CPU:1415 MH。
在第三种情况下,我检查了数据库端,等待事件是“从客户的SQL * Net的更多的数据。” 这意味着服务器等待来自客户端更多的数据。
第三种方法的结果是令人难以置信的,我没有测试。
所以从我的短的建议是只使用executemany。
文章来源: How can I do a batch insert into an Oracle database using Python?