22

要件 : 整数、文字列、リスト、辞書などの基本的なデータ型を含む 2 ~ 3 レベルのネストを持つ Python オブジェクト。(日付などはありません)、キーに対してredisにjsonとして保存する必要があります。低メモリフットプリントのためにjsonを文字列として圧縮するために利用できる最良の方法は何ですか. 対象オブジェクトはそれほど大きくなく、平均で 1000 個の小さな要素、JSON に変換すると約 15000 文字です。

例えば。

>>> my_dict
{'details': {'1': {'age': 13, 'name': 'dhruv'}, '2': {'age': 15, 'name': 'Matt'}}, 'members': ['1', '2']}
>>> json.dumps(my_dict)
'{"details": {"1": {"age": 13, "name": "dhruv"}, "2": {"age": 15, "name": "Matt"}}, "members": ["1", "2"]}'
### SOME BASIC COMPACTION ###
>>> json.dumps(my_dict, separators=(',',':'))
'{"details":{"1":{"age":13,"name":"dhruv"},"2":{"age":15,"name":"Matt"}},"members":["1","2"]}'

1/ json を圧縮して redis のメモリを節約するための他のより良い方法はありますか (また、後で軽量のデコードを確実にします)。

2/ msgpack [http://msgpack.org/] はどの程度の候補になるでしょうか?

3/ ピクルスなどのオプションも検討しますか?

4

6 に答える 6

19

gzipコンプレッサーとして使っているだけです。

import gzip
import cStringIO

def decompressStringToFile(value, outputFile):
  """
  decompress the given string value (which must be valid compressed gzip
  data) and write the result in the given open file.
  """
  stream = cStringIO.StringIO(value)
  decompressor = gzip.GzipFile(fileobj=stream, mode='r')
  while True:  # until EOF
    chunk = decompressor.read(8192)
    if not chunk:
      decompressor.close()
      outputFile.close()
      return 
    outputFile.write(chunk)

def compressFileToString(inputFile):
  """
  read the given open file, compress the data and return it as string.
  """
  stream = cStringIO.StringIO()
  compressor = gzip.GzipFile(fileobj=stream, mode='w')
  while True:  # until EOF
    chunk = inputFile.read(8192)
    if not chunk:  # EOF?
      compressor.close()
      return stream.getvalue()
    compressor.write(chunk)

このユースケースでは、ご想像のとおり、結果をファイルとして保存します。メモリ内の文字列だけを使用するにはcStringIO.StringIO()、ファイルの代わりにオブジェクトを使用することもできます。

于 2013-03-20T16:34:26.497 に答える
2

簡単な「後処理」の方法の 1 つは、「短いキー名」マップを作成し、生成された json を保存前に実行し、オブジェクトに逆シリアル化する前に再度 (逆に) 実行することです。例えば:

Before: {"details":{"1":{"age":13,"name":"dhruv"},"2":{"age":15,"name":"Matt"}},"members":["1","2"]}
Map: details:d, age:a, name:n, members:m
Result: {"d":{"1":{"a":13,"n":"dhruv"},"2":{"a":15,"n":"Matt"}},"m":["1","2"]}

json を調べて、データベースへの途中で key->value を置き換え、アプリケーションへの途中で value->key を置き換えるだけです。

さらに便利なように gzip することもできます (ただし、その後は文字列にはなりません)。

于 2013-03-21T09:50:35.390 に答える
0

もう 1 つの可能性は、MongoDB のストレージ形式であるBSONを使用することです。

そのサイトの実装ページで 2 つの Python 実装を見つけることができます。

編集:辞書を保存して、取得時にjsonに変換しないのはなぜですか?

于 2013-03-20T14:10:39.620 に答える