ASCII 데이터 파일을 구문 분석하여 데이터를 테이블로 가져올 때도이 문제가 발생했습니다. 문제는 필자가 직관적으로 직관적으로 SQLAlchemy가 고유 한 데이터를 허용하면서 중복 된 행을 건너 뛰길 바랬다는 것입니다. 또는 유니 코드 문자열이 허용되지 않는 등 현재 SQL 엔진으로 인해 행에 임의의 오류가 발생하는 경우 일 수 있습니다.
그러나이 동작은 SQL 인터페이스의 정의 범위를 벗어납니다. SQL API 및 따라서 SQLAlchemy는 트랜잭션과 커밋 만 이해하며 이러한 선택적 동작을 설명하지 않습니다. 게다가 예외가 발생하면 삽입이 중단되어 나머지 데이터는 남겨 지므로 자동 커밋 기능에 의존하는 것이 위험합니다.
내 솔루션 (가장 우아한 것인지 확실하지 않음)은 루프의 모든 행을 처리하고 예외를 캐치 및 로그하며 맨 끝에 변경 사항을 커밋하는 것입니다.
당신이 어떻게 든 목록 목록 (즉, 열 값 목록 인 행 목록)에서 데이터를 획득했다고 가정합니다. 그런 다음 루프의 모든 행을 읽습니다.
# Python 3.5
from sqlalchemy import Table, create_engine
import logging
# Create the engine
# Create the table
# Parse the data file and save data in `rows`
conn = engine.connect()
trans = conn.begin() # Disables autocommit
exceptions = {}
totalRows = 0
importedRows = 0
ins = table.insert()
for currentRowIdx, cols in enumerate(rows):
try:
conn.execute(ins.values(cols)) # try to insert the column values
importedRows += 1
except Exception as e:
exc_name = type(e).__name__ # save the exception name
if not exc_name in exceptions:
exceptions[exc_name] = []
exceptions[exc_name].append(currentRowIdx)
totalRows += 1
for key, val in exceptions.items():
logging.warning("%d out of %d lines were not imported due to %s."%(len(val), totalRows, key))
logging.info("%d rows were imported."%(importedRows))
trans.commit() # Commit at the very end
conn.close()
이 작업의 속도를 최대화하려면 자동 커밋을 비활성화해야합니다. 나는이 코드를 SQLite와 함께 사용하고 있으며 자동 체크가 비활성화 된 상태에서도 여전히 sqlite3
을 사용하는 이전 버전보다 3-5 배 느리다. (SQLAlchemy로 이식 한 이유는 MySQL과 함께 사용할 수 있기 때문입니다.)
SQLite에 대한 직접 인터페이스만큼 빠르지 않은 가장 우아한 솔루션은 아닙니다. 머지 않아 코드를 프로파일 링하고 병목 현상을 발견하면이 대답을 솔루션으로 업데이트 할 것입니다.