데이터베이스에 대해 일련의 동적 생성 쿼리를 실행하고 결과를 가져 오는 최종 쿼리를 최종적으로 수행하는 구성 요소를 작성했습니다. 이 모든 로직은 생성기에 래핑됩니다. 다른 구성 요소는이 생성기에 연결하여 결과를 파일 (이 테스트의 경우 탭으로 구분 된 텍스트 파일)에 스풀링 할 수 있습니다.cx_Oracle 커서가 몇 분 동안 멈춤 루프
def cycle(self, schema, matchprofile, fixedcond):
cursor = self.cursor
cursor.set_schema(schema)
cursor.execute('TRUNCATE TABLE schema.table')
metaatts = self.get_metaattributes(schema)
for condset in matchprofile:
condsql = self.dostuffwith(self, matchprofile, fixedcond)
qry = self.qrybase.replace('<<condset>>', condset).replace('<<condsql>>', condsql)
cursor.execute(qry) # queries performing logic aganst database
cursor.execute(self.finalqry) # select query extracting results
for row in cursor:
yield Row(row, metaatts.copy())
if self.counts:
self.counter.addto(cursor.rowcount)
cursor
는 서브 클래스 'cx_Oracle.Cursor가'증가 arraysize
유니 코드 문자열로 변환하는 outputtypehandler
함께 여기 발생기 함수의 코드가있다. cycle
은 여러 입력 스키마의 출력을 하나의 스트림으로 묶는 다른 메서드에서 호출됩니다.
cycles = itertools.imap(self.cycle, schemas, itertools.repeat(matchprofile), itertools.repeat(fixedcond))
rows = itertools.chain.from_iterable(cycles)
저는 이것을 Python 2.6에서 실행합니다.
이미 전체 스크립트를 수십 번 실행했으며 대부분의 경우 데이터베이스 스키마를 완료하는 데 약 11-12 분이 걸렸습니다. 이것은 예상 이상입니다. 예상치 못한 나에게, 일부 시도에서 스크립트는 약 55 초 만에 완료되었습니다. 그것은 제가 대체하려고하는 레거시 스크립트의 성능을 기반으로 기대했던 것입니다.
새 도구는 입력 매개 변수로 여러 데이터베이스 스키마를 사용할 수 있으므로 동일한 스키마를 6 번 제공하여 테스트를 수행했습니다. 나는 또한 합리적인 생산 실행을 프로파일 관리
:: 1597 records in 11:33
:: 1597 records in 0:56
:: 1597 records in 0:55
:: 1597 records in 0:55
:: 1597 records in 0:55
:: 1597 records in 0:55
:: total 9582 records in 16:10
...
109707 function calls (109627 primitive calls) in 57.938 CPU seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
12 56.154 4.679 56.154 4.680 {function execute at 0x010074B0}
1 0.819 0.819 0.819 0.819 ora.py:194(__init__)
1 0.387 0.387 0.387 0.387 {function parse at 0x010075B0}
1598 0.331 0.000 56.543 0.035 DuplicateDetector.py:219(cycle)
1598 0.118 0.000 0.118 0.000 {method 'writerow' of '_csv.writer' objects}
30295 0.029 0.000 0.029 0.000 {_codecs.utf_8_decode}
1598 0.025 0.000 56.720 0.035 dsv.py:146(generate)
30310 0.022 0.000 0.029 0.000 {method 'encode' of 'unicode' objects}
... 과도한 타이밍 : 로그인 한 실행 시간은 문제가 첫 번째 반복에서 발생 표시했다.
109707 function calls (109627 primitive calls) in 701.093 CPU seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1598 644.514 0.403 699.827 0.438 DuplicateDetector.py:219(cycle)
12 55.247 4.604 55.248 4.604 {function execute at 0x010084B0}
1 0.783 0.783 0.783 0.783 ora.py:194(__init__)
1 0.283 0.283 0.283 0.283 {function parse at 0x010085B0}
1598 0.121 0.000 0.121 0.000 {method 'write' of '_csv.writer' objects}
30295 0.036 0.000 0.036 0.000 {_codecs.utf_8_decode}
1598 0.025 0.000 700.006 0.438 dsv.py:146(generate)
30310 0.022 0.000 0.028 0.000 {method 'encode' of 'unicode' objects}
30295 0.021 0.000 0.057 0.000 utf_8.py:15(decode)
그것은 첫 번째 경우에 데이터베이스 작업의 시간 후자의 대부분, 실행 시간의 대부분을하면서 cycle
발전기에 소요되는 것을 분명하다. Idle 디버거를 사용하여이 단계를 단계별로 실행했으며 약 10 분의 실행 시간은 for row in cursor:
입니다. 나는 또한 그 시간 동안 python.exe 프로세스의 메모리 사용량이 지속적으로 증가한다는 것을 알아 차렸다.
이제는 동일한 코드의 실행 시간이 매우 다르기 때문에 그 행에서 어떤 문제가 발생합니까? Cursor가 반복자로 사용될 때 cx_Oracle은 내부적으로 어떤 종류의 연산을 수행합니까? 이 오류를 일으키는 배치 코드에서 내가 실수했을 수있는 점은 무엇입니까? 틀림없이 클래스 나 생성자를 사용하지 않은 이전 스크립트에서는 비슷한 것을 발견하지 못했지만 단순히 커서에서 fetchall
을 수행했습니다.
미리 감사드립니다.