読者です 読者をやめる 読者になる 読者になる

MySQLdbの使い方

MySQLdbとは

MySQLPythonサポート用モジュール。MySQLdb(version1.2.2)はMySQLのversion3.23-5.1をサポートし、Pythonのversion2.3-2.5で動作する。
ダウンロードはここ

MySQLdb version1.2.2の簡単な使い方。

import MySQLdb
# MySQLデータベースに接続するにはMySQLdb.connectを用いる
# 引数に指定できるのは下のやつ(MySQL C APIに準拠)
# host, user, passwd, db, port, unix_socket, conv, connect_timeout, compress, named_pipe, init_command, read_default_file, read_default_group, cursorclass, use_unicode, charset, sql_mode, client_flag, ssl, local_infile
db = MySQLdb.connect(db="data", host="localhost", user="root", passwd="***")
# カーソルの作成
c = db.cursor()
sql = "SELECT * FROM log"
# sqlの実行
c.execute(sql)

ここまでで、dataデータベースにあるlogテーブルの全てのカラムを取得することができた。
取得結果へのアクセスの方法は3種類

fetchone()を用いる方法

fetchone()を用いると順々にアクセスする。最後までいったらNoneを返すので、全てのレコードに一回ずつ出力するには

record = c.fetchone() 
while record != None:
    print record
    c.fetchone()
fetchall()を用いる方法

fechall()は全てのデータを詰め込んだリストを返す。

records = c.fechall()
for record in records:
    print record
fetchmany(n)を用いる方法

fechmany(n)はn個のデータを詰め込んだリストを返す。デフォルトでnは1

records = c.fechmany(10)
for record in records:
    print record
考察

fechall()は全てのデータをリストにするため、そのあとの一つ一つにアクセスするのは速いが、該当データが巨大だった場合にメモリを大量に消費する。一方、fechone()はイテレータを用いているのでメモリを節約できそうだけど、その代りsqlの発行回数が増加する。
なので、「数少ないうちはfechall()で一括してとってくる。多くなったら、fechone()を使うか、ある程度の規模で区切ってとってこれるようにsqlを工夫してそれらに対してfechall()を用いる」といいのかも。
例えば、idに対して1000個区切りでとってくるにはsqlを以下のようにすればいいのか?

# データが1,000,000個あったとして、それを1000個ずつとってきてfechall()でアクセス
for i in range(1000):
    c.execute("""SELECT * FROM log
              WHERE id BETWEEN %s AND %s""", (1+1000*i, 1000*(i+1)))
    records = c.fetchall()
    for record in records:
        print record