2

やあみんな、私は次の問題を抱えています: 1 つのプロセスが非常に大きなクエリを実行し、結果をファイルに書き込みます。その間に、プロセスはステータスをデータベースに更新する必要があります。

最初に考えた:問題なし、疑似コード:

db = mysqldb.connect()
cursor = db.cursor()
large = cursor.execute(SELECT * FROM VERYLARGETABLE)
for result in large.fetchall():
     file.write(result)
if timetoUpdateStatus: cursor.execute(UPDATE STATUS)

問題: 900 万の結果を取得すると、「large = cursor.execute(SELECT * FROM VERYLARGETABLE)」が終了しません... mysql サーバーが 30 秒後にクエリを終了した 4 列で 200 万エントリの境界を見つけましたが、 python プロセスが何時間も実行され続けます...これはおそらく Python MySQLDB ライブラリのバグです..

SO 2 回目の試行: db.use_results() および fetch_row() を使用した db.query 関数:

db = mysqldb.connect()
cursor = db.cursor()
db.query(SELECT * FROM VERYLARGETABLE)
large = large.use_result()
while true:
    for row in large.fetch_row(100000):
        file.write(row)
    if timetoUpdateStatus: cursor.execute(UPDATE STATUS) <-- ERROR (2014, "Commands out of sync; you can't run this command now")

そのため、3 回目の試行では 2 つの MySQL 接続を使用していました...これは機能しません。2 番目の接続を開くと、最初の接続が消えます....

助言がありますか??

4

3 に答える 3

6

MySQL SSCursorを使用してみてください。デフォルトのカーソルが行うように、結果セットをクライアント (Python データ構造) に転送するのではなく、サーバー (MySQL データ構造) に結果セットを保持します。SSCursor を使用すると、既定のカーソルが Python データ構造を構築しようとすることによって引き起こされる長い初期遅延を回避し、巨大な結果セットにメモリを割り当てます。したがって、SSCursor に必要なメモリも少なくて済みます。

import MySQLdb
import MySQLdb.cursors
import config

cons = [MySQLdb.connect(
    host=config.HOST, user=config.USER,
    passwd=config.PASS, db=config.MYDB,
    cursorclass=MySQLdb.cursors.SSCursor) for i in range(2)]
select_cur, update_cur = [con.cursor() for con in cons]
select_cur.execute(SELECT * FROM VERYLARGETABLE)
for i, row in enumerate(select_cur):
    print(row)
    if i % 100000 == 0 or timetoUpdateStatus:
        update_cur.execute(UPDATE STATUS)
于 2011-05-17T19:04:18.880 に答える
4

「select * from db」クエリを小さなチャンクに分割してみてください

index=0
while True:
    cursor.execute('select * from verylargetable LIMIT %s,%s', (index, index+10000))
    records = cursor.fetchall()
    if len(records)==0:
          break
    file.write(records)
    index+=10000
file.close()
于 2011-05-17T18:36:45.063 に答える
2

大きな選択で次のステートメントを使用しLIMITます。

limit = 0
step = 10000
query = "SELECT * FROM VERYLARGETABLE LIMIT %d, %d"
db = mysqldb.connect()
cursor = db.cursor()
while true:
    cursor.execute(query, (step, limit))
    for row in cursor.fetch_all():
        file.write(row)
    if timetoUpdateStatus:
        cursor.execute(update_query)
    limit += step

コードはテストされていませんが、アイデアは得られるはずです。

于 2011-05-17T18:33:38.980 に答える