source

파이썬을 사용하여 오라클 데이터베이스에 배치 삽입을 수행하려면 어떻게 해야 합니까?

manycodes 2023. 7. 20. 22:02
반응형

파이썬을 사용하여 오라클 데이터베이스에 배치 삽입을 수행하려면 어떻게 해야 합니까?

Oracle 데이터베이스 테이블에 삽입하고 싶은 월간 날씨 데이터가 몇 개 있지만 보다 효율적으로 사용하기 위해 해당 기록을 일괄적으로 삽입하고 싶습니다.Python에서 이 작업을 수행하는 방법에 대해 조언할 수 있는 사람이 있습니까?

예를 들어, 내 표에 스테이션 ID, 날짜 및 두 개의 값 필드의 네 개의 필드가 있다고 가정해 보겠습니다.레코드는 스테이션 ID 및 날짜 필드(합성 키)로 고유하게 식별됩니다.각 스테이션에 대해 입력해야 하는 값은 X개의 전체 연도 값이 있는 목록에 유지되므로, 예를 들어 2년 값이 있는 경우 값 목록에는 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 접근 방식과 비교한 설명/예시를 제공할 수 있다면 특히 도움이 될 것입니다.

편집: 커서를 사용해야 할 것 같습니다.여기에 설명된 바와 같이 많은 것을 실행합니까?

제안, 의견 등에 대해 미리 감사드립니다.

잘 작동하는 것으로 보이는 것은 다음과 같습니다(그러나 이를 개선할 수 있는 방법이 있다면 의견을 제시해 주십시오)

# 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()

사용하다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 기사 시리즈.

댓글 중 하나에서 언급한 것처럼, 사용을 고려해 보십시오.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

fii 내 테스트 결과:

저는 5000줄에 삽입합니다.행당 3개의 열이 있습니다.

  1. 인서트를 5000번 실행합니다. 비용은 1.24분입니다.
  2. 실행 시간은 0.125초입니다.
  3. 모든 코드를 삽입하여 실행합니다. 비용은 4.08분입니다.

t(a,b,c)에 sql like insert all을 설정하는 파이썬 코드는 듀얼 유니언에서 :1, :2, :3을 선택합니다. 모두 daul에서 :4, :5::6을 선택합니다...

이 긴 SQL을 설정하기 위한 파이썬 코드, 비용은 0.145329초였습니다.

저는 아주 오래된 태양 기계에서 제 코드를 테스트합니다. cpu: 1415 MH.

세 번째 경우, 데이터베이스 측면을 확인했는데, 대기 이벤트는 "SQL*클라이언트의 데이터 추가"입니다.즉, 서버가 클라이언트로부터 더 많은 데이터를 기다리고 있습니다.

세 번째 방법의 결과는 시험 없이는 믿을 수 없습니다.

그래서 제가 제안한 짧은 제안은 단지 경영진을 많이 이용하는 것입니다.

union을 사용하여 큰 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에서 문자열을 빌드하고 오라클에 하나의 문으로 제공하여 실행할 수 있습니다.

언급URL : https://stackoverflow.com/questions/14904033/how-can-i-do-a-batch-insert-into-an-oracle-database-using-python

반응형