programing

python에서 행별로 MySQL ResultSet을 가져오는 방법

javaba 2022. 10. 26. 21:32
반응형

python에서 행별로 MySQL ResultSet을 가져오는 방법

MySQL ResultSets는 기본적으로 작업을 수행하기 전에 서버에서 완전히 가져옵니다.결과 세트가 큰 경우 이 값은 사용할 수 없게 됩니다.그 대신 서버에서 행을 하나씩 가져오고 싶습니다.

Java에서는 ("ResultSet" 아래)의 지시에 따라 다음과 같은 문장을 작성합니다.

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
              java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

이것은 Java에서 잘 동작합니다.질문입니다. 비단뱀에게도 같은 방법이 있을까요?

한 번에 1000줄로 쿼리를 제한하려고 했습니다.이렇게 됩니다.

start_row = 0
while True:
    cursor = conn.cursor()
    cursor.execute("SELECT item FROM items LIMIT %d,1000" % start_row)
    rows = cursor.fetchall()
    if not rows:
        break
    start_row += 1000
    # Do something with rows...

단, start_row가 높을수록 속도가 느려지는 것 같습니다.

아니요, 리고아,,를 사용해서fetchone()fetchall()아무것도 변하지 않아

설명:

이 문제를 재현하기 위해 사용하는 순진한 코드는 다음과 같습니다.

import MySQLdb

conn = MySQLdb.connect(user="user", passwd="password", db="mydb")
cur = conn.cursor()
print "Executing query"
cur.execute("SELECT * FROM bigtable");

print "Starting loop"
row = cur.fetchone()
while row is not None:
    print ", ".join([str(c) for c in row])
    row = cur.fetchone()

cur.close()
conn.close()

최대 700,000 행 테이블에서는 이 코드가 빠르게 실행됩니다.그러나 약 9,000,000 행의 테이블에서는 "쿼리 실행 중"이 인쇄된 후 장시간 중단됩니다.그렇기 때문에 이 제품을 사용해도 아무런 차이가 없는 것입니다.fetchone() ★★★★★★★★★★★★★★★★★」fetchall().

해야 할 것 요.cursorclass = MySQLdb.cursors.SSCursor:

 MySQLdb.connect(user="user", 
                 passwd="password",
                 db="mydb",
                 cursorclass = MySQLdb.cursors.SSCursor
                )

커서는 를 한 데이터는 사용하지 않아도 .fetchall.

집::SSCursor 측 세트를 - 합니다.MySQLdb.cursors.

mysql이 오프셋을 찾기 위해 행을 다시 검색해야 하므로 한계/오프셋 솔루션은 2차 시간 내에 실행됩니다.예상대로 기본 커서는 클라이언트에 전체 결과 세트를 저장하므로 메모리가 많이 소모될 수 있습니다.

대신 서버 측 커서를 사용하여 쿼리를 계속 실행하고 필요에 따라 결과를 가져올 수 있습니다.커서 클래스는 연결 호출 자체에 기본값을 지정하거나 매번 커서 메서드에 클래스를 지정함으로써 맞춤화할 수 있습니다.

from MySQLdb import cursors
cursor = conn.cursor(cursors.SSCursor)

하지만 그게 전부는 아니다.mysql 결과를 저장할 뿐만 아니라 기본 클라이언트 측 커서가 실제로 모든 행을 가져옵니다.이 동작은 문서화되어 있지 않기 때문에 매우 유감입니다.즉, 모든 행에 대해 완전한 python 객체가 생성되어 원래 mysql 결과보다 훨씬 더 많은 메모리가 소비됩니다.

대부분의 경우 클라이언트에 저장된 결과를 반복기로 포장하면 적절한 메모리 사용률로 최상의 속도를 얻을 수 있습니다.하지만 그걸 원하시면 직접 굴리셔야 합니다.

이 버전의 페톤을 먹어봤어?아니면 다른 거?

row = cursor.fetchone() 
while row is not None:
    # process
    row = cursor.fetchone()

그리고 이거 먹어봤어?

 row = cursor.fetchmany(size=1)
 while row is not None:
     # process
     row = cursor.fetchmany( size=1 )

모든 드라이버가 이러한 기능을 지원하는 것은 아니기 때문에 오류가 발생하거나 속도가 너무 느릴 수 있습니다.


편집.

실행 중이면 데이터베이스를 기다리는 것입니다.이것은 Python을 한 줄씩 나열하는 것이 아니라 MySQL입니다.

MySQL은 자체 캐시 관리의 일부로 모든 행을 가져오는 것을 선호합니다.이것은 Integer의 fetch_size를 지정함으로써 비활성화됩니다.MIN_VALUE(-2147483648L).

문제는 Python DBAPI의 어떤 부분이 JDBC fetch_size와 동등해지는가 하는 것입니다.

커서의 배열 크기 특성일 수 있습니다.해라

cursor.arraysize=-2**31

또한 MySQL이 결과 세트를 캐싱하는 대신 스트리밍해야 하는지 확인합니다.

MySQLdb.cursors를 사용해 보겠습니다.SSDict Cursor

con = MySQLdb.connect(host=host,
                  user=user,
                  passwd=pwd,
                  charset=charset,
                  port=port,
                  cursorclass=MySQLdb.cursors.SSDictCursor);
cur = con.cursor()
cur.execute("select f1, f2 from table")
for row in cur:
    print row['f1'], row['f2']

나는 다른 대답들과 약간 섞여서 가장 좋은 결과를 찾았다.

여기에는 설정이 포함되어 있습니다.cursorclass=MySQLdb.cursors.SSDictCursor(MySQLdb의 경우) 또는pymysql.cursors.SSDictCursor(PyMySQL의 경우)를 연결 설정의 일부로 사용합니다.그러면 서버가 쿼리/결과('SS'는 결과를 가져오는 기본 커서가 아닌 서버 측을 의미)를 유지하고 각 행에서 사전을 빌드할 수 있습니다(예: {'id': 1, '이름': '쿠키 몬스터').

그리고 행을 루프하기 위해 Python 2.7과 3.4에 무한 루프가 발생했습니다.while rows is not None왜냐하면cur.fetchmany(size=10000)호출되어 남은 결과가 없습니다.메서드는 빈 목록을 반환했습니다( ).[](없음)이 아닌 )을 클릭합니다.

실제 예:

query = """SELECT * FROM my_table"""
conn = pymysql.connect(host=MYSQL_CREDENTIALS['host'], user=MYSQL_CREDENTIALS['user'],
                          passwd=MYSQL_CREDENTIALS['passwd'], charset='utf8', cursorclass = pymysql.cursors.SSDictCursor)
cur = conn.cursor()
results = cur.execute(query)
rows = cur.fetchmany(size=100)
while rows:
    for row in rows: 
        process(row)
    rows = cur.fetchmany(size=100)
cur.close()
conn.close()

언급URL : https://stackoverflow.com/questions/337479/how-to-get-a-row-by-row-mysql-resultset-in-python

반응형