8.5 NoSQL データストア
一部のデータベースはリレーショナルではなく、SQLをサポートしていません。これらは、非常に大きなデータセットの処理や柔軟なデータ定義を目的としており、NoSQL (Not Only SQL) と総称されています。
8.5.1 dbmファミリ
Section titled “8.5.1 dbmファミリ”dbmはNoSQLという言葉が生まれる前から存在する、シンプルなキーバリューストア(キーと値の組)です。Pythonの辞書とよく似た操作感で、ディスク上のファイルに直接データを保存できます。
import dbm
# 'c'モードは読み書き両用で、ファイルがなければ作成するdb = dbm.open('definitions', 'c')
# 辞書のようにキーに値を代入して保存db['mustard'] = 'yellow'db['ketchup'] = 'red'
# データの取得(バイト列として返される)print(db['mustard']) # b'yellow'
db.close()8.5.2 memcached
Section titled “8.5.2 memcached”memcachedは、キーと値のための高速な「インメモリ」のキャッシュサーバーです。データは永続的ではなく、メモリが不足すると古いデータから消去されていきます。
Pythonから操作するには、python-memcached などのサードパーティ製ドライバを使用します。
# pip install python-memcached が必要import memcache
# memcachedサーバーに接続db = memcache.Client(['127.0.0.1:11211'])
# 値の設定と取得db.set('marco', 'polo')print(db.get('marco')) # 'polo'
# 数値のインクリメントdb.set('ducks', 0)db.incr('ducks', 2)print(db.get('ducks')) # 28.5.3 Redis
Section titled “8.5.3 Redis”Redisは、memcachedに似ていますが、データをディスクに保存して再起動に対応できたり、単純な文字列以外の多様なデータ構造(リスト、ハッシュ、集合など)を扱えたりする強力なデータ構造サーバーです。
# redis-py ドライバのインストール$ pip install redisimport redis
# Redisサーバーに接続(デフォルトで localhost:6379)conn = redis.Redis()文字列と数値の操作
Section titled “文字列と数値の操作”conn.set('secret', 'ni!')print(conn.get('secret')) # b'ni!'
conn.set('carats', 24)conn.incr('carats', 10) # 10増やすprint(conn.get('carats')) # b'34'リスト(List)
Section titled “リスト(List)”Redisのリストは文字列のみを格納できます。先頭(lpush)や末尾(rpush)への追加が可能です。
# 先頭に要素を追加conn.lpush('zoo', 'bear', 'alligator', 'duck')
# 全要素を取得 (0 から -1 は全体を意味する)print(conn.lrange('zoo', 0, -1))# [b'duck', b'alligator', b'bear']ハッシュ(Hash)
Section titled “ハッシュ(Hash)”Pythonの辞書に似ていますが、値は文字列のみです。1段階の深さのキー・バリューのペアを保持します。
conn.hmset('song', {'do': 'a deer', 're': 'about a deer'})conn.hset('song', 'mi', 'a note to follow re')
print(conn.hgetall('song'))# {b'do': b'a deer', b're': b'about a deer', b'mi': b'a note to follow re'}集合(Set)とソート済み集合(Sorted Set / zset)
Section titled “集合(Set)とソート済み集合(Sorted Set / zset)”重複のない要素の集まりを扱います。和集合や積集合などの集合演算も可能です。 また、各要素に「スコア」を持たせて順序付けできるソート済み集合は、タイムラインやランキングに非常に便利です。
import time
# ソート済み集合の例:タイムスタンプをスコアとしてログイン履歴を記録now = time.time()conn.zadd('logins', {'smeagol': now})conn.zadd('logins', {'sauron': now + 300}) # 5分後
# ログイン順に取得print(conn.zrange('logins', 0, -1, withscores=True))キャッシュと有効期限
Section titled “キャッシュと有効期限”Redisの全てのキーには有効期限を設定でき、指定した時間が経過すると自動的に削除されます。
conn.set('temp_key', 'hello')conn.expire('temp_key', 5) # 5秒後に削除されるように設定