パイソンを使用して、読み取り専用のバイナリフラットファイルストレージのオプション
-
20-09-2019 - |
質問
私は限られた記憶とプロセッサ速度を有する組み込み機器で使用するためのフラットファイルSKUデータベースの設定を担当されています。
基本的に私が店に必要なデータは、次の要素で構成されます:
SKU 説明 ロケーション 価格 数量
ファイルには、数百万のレコードで構成されます。
最も重要な考慮事項は、ストレージスペースと検索時間です。レコードのみSKUによって取得する必要があります、それは読み取り専用になりますので、ファイルがSKUでソートできます。
私は、Pythonでこのデータにアクセスしたいと思います。だから私の質問はこれに尽きるます。
私のためにこの機能を提供することができ、既存のPythonライブラリはありますか、私は自分自身をロールバックする必要がありますか?
答えは自分自身をロールバックするダウンしていた場合は、、誰もがそうするための提案、または良いの参照を持っているのですか?
解決
どのようにPythonバインディングを持つ SQLiteののでしょうか?それはあなたが必要とするより少しを持っているが、それは標準的なソフトウェアだと十分にテストされた。
他のヒント
古い方法は、GDBMモジュールのような単純なキー/値データテーブルを用いることであろう。 Pythonはそのためのサポートが付属していますが、それは私のマシン上のデフォルトのPythonのインストールに組み込まれていない。
一般的には、SQLiteのを使用しています。他の人が書いたように、それは、Pythonが標準装備されています、それはすでに組み込みシステムの多くで使われています。
レコードは長さが固定されている場合は、あなたは二分モジュールを使用することができます。ファイルサイズは/レコード・サイズは、ファイル内のレコードの数を示します。二分検索は、ファイル内のO(ログ(N))のルックアップを行います、あなたは平等のためにテストするためのアダプタを書く必要があります。私はそれをテストしていませんが、ここではスケッチです:
import bisect
RECORD_SIZE = 50
class MatchFirst10Chars(object):
def __init__(self, word):
self.word = word
def __lt__(self, other):
return self.word < other[:10]
class FileLookup(object):
def __init__(self, f):
self.f = f
f.seek(0, 2)
self.size = f.tell() // RECORD_SIZE
def __len__(self):
return self.size
def __getitem__(self, i):
self.f.seek(i*RECORD_SIZE)
return self.f.read(RECORD_SIZE)
SKU = "123-56-89 "
f = open("data_file")
fl = FileLookup(f)
i = bisect.bisect(fl, MatchFirst10Chars(SKU))
あなたが追加したファイルをgzipとgzip'pedファイルに求めるが、それはあなたがテストする必要があります対時間のスペースのためのトレードオフだ可能性があります。
私は CDB を示唆するかもしれませんか? (Pythonバインディング:のpython-CDB の)
あなたが持っているように、これは、読み取り専用データのために使用される形式です。それは基本的に256の巨大なハッシュテーブル、バケツの数が異なることができ、それぞれです。 CDBについてのクールなことは、ファイルがメモリにロードする必要がないということです。それはあなたがちょうどあなたが必要とするビットにmmap
ingで検索を行うことができる方法で構造化されます。
CDBスペックには線がフォーマットされていない少なくともので、良い読み取られ均一な右マージンを作成します。 :-D
どのように HDF のでしょうか?あなたがSQLを必要とし、データへの高速アクセスを必要としない場合は、より高速なものはありません... Pythonで...数値または構造化データのために。
<のhref = "HTTP上の DatabaseInterfaces のセクションを見てみましょう:/ /www.python.org/」のrel = "nofollowをnoreferrer"> Pythonののウィキ。それは包括的です。少しよりよいです( SnakeSQL のように)記載されている「純粋な」Pythonのオプションのいくつかあります展開します。そして、もちろん、常にのBerkeley DB と&スーパーリーンである、などのがあります生ます。
正直なところ、SQLiteはおそらくあなたのために正常に動作します。あなたは本当に多くのパフォーマンスをEEKする必要がある場合は、BDBのようなレコードベースの形式を見ていると思います。
簡単な解決策は、はcPickle のです。また、<のhref = "https://stackoverflow.com/questions/890485/python-how-do-i-write-a-list-to-file-and-then-pull-it-back-into見つけることができます-memory-dictの-REP ">同様の質問がSOにします。
アンドリューDalkeの答えの変動はすべて、ファイル(SKUごとに1)の開始時に固定サイズのレコードを持っていることであろうスペース要件を低減することができる(そう、あなたはまだすぐにSKUを見つけるためにバイナリ検索を使用することができます)と、説明と場所(ヌル文字列が言うに終了される)
あなたは、固定長の場所と説明アウトパッドに持っていないことで、スペースを節約するために得ます。また、重複した場所の多くは、
がある場合は、スペースを節約することができますここでは一例です: あなたが持っていると言う。
SKU 16 bytes
Description Variable length
Location Variable length
Price 4 bytes (up to $42949672.95)
Quantity 4 bytes (up to 4294967295)
offset SKU desc_off loc_off Price Quantity
0x00000000 SKU0000000000001 0x01f78a40 0x01f78a47 0x000003e8 0x000f4240
0x00000020 SKU0000000000002 0x01f78a53 0x01f78a59 ...
...
... # 999998 more records
...
0x01f78a40 Widget\x00
0x01f78a47 Head office\x00
0x01f78a53 Table\x00
0x01f78a59 Warehouse\x00