如果我们有一些代码(数据结构)应该存储在数据库中,有人总是建议我们存储序列化数据而不是原始代码字符串。
所以我不太确定为什么我们应该更喜欢序列化数据。
举一个简单的例子(python):
我们有一个字段可以存储 python 的字典,比如
{ "name" : "BMW", "category":"car", "cost" : "200000"}
所以我们可以使用 pickle(一个 python 模块)将其序列化,然后将 pickle 数据存储到 db 字段。
或者我们可以不序列化直接将dict字符串存入DB。
由于我们需要将字符串转换回 python 数据,因此两种方法都很容易实现,分别使用 pickle.loads 和 exec。
那么应该首选哪个?为什么?是因为 exec 比 pickle 慢得多吗?还是其他原因?
谢谢。
最佳答案
Or we can store the dict string directly to DB without serializing.
没有“字典字符串”这样的东西。有很多方法可以将字典序列化为字符串;你可能会想到 repr
,可能是 eval
作为获取 dict 的方式(你提到 exec
,但这简直是荒谬的:什么语句你会执行...?!我想你可能是指 eval
)。它们是不同的序列化方法及其权衡,在许多情况下,权衡倾向于支持酸洗(cPickle
,为了速度,协议(protocol) -1
意思是“最好的你可以做”,通常)。
性能肯定是一个问题,例如,就您存储的内容的大小而言...:
$ python -c 'import cPickle; d=dict.fromkeys(range(99), "banana"); print len(repr(d))'
1376
$ python -c 'import cPickle; d=dict.fromkeys(range(99), "banana"); print len(cPickle.dumps(d,-1))'
412
...为什么每次序列化像这样的字典时要存储 1.4 KB 而不是 0.4 KB...?-)
编辑:由于有人建议使用 Json,因此值得指出的是 json 在这里占用 1574 个字节——甚至比庞大的 repr 还要庞大!
至于速度...
$ python -mtimeit -s'import cPickle; d=dict.fromkeys(range(99), "chocolate")' 'eval(repr(d))'
1000 loops, best of 3: 706 usec per loop
$ python -mtimeit -s'import cPickle; d=dict.fromkeys(range(99), "chocolate")' 'cPickle.loads(cPickle.dumps(d, -1))'
10000 loops, best of 3: 70.2 usec per loop
...为什么要花 10 倍的时间?付出如此高昂的代价有什么好处?
编辑:json 需要 2.7 毫秒秒 -- 几乎比 cPickle 慢四十倍。
然后是通用性——并非每个可序列化对象都可以使用 repr 和 eval 正确往返,而酸洗则更为通用。例如:
$ python -c'def f(): pass
d={23:f}
print d == eval(repr(d))'
Traceback (most recent call last):
File "<string>", line 3, in <module>
File "<string>", line 1
{23: <function f at 0x241970>}
^
SyntaxError: invalid syntax
对比
$ python -c'import cPickle
def f(): pass
d={"x":f}
print d == cPickle.loads(cPickle.dumps(d, -1))'
True
编辑:就往返而言,json 甚至不如 repr 通用。
因此,比较两种序列化方法(pickling 与 repr/eval),我们看到:pickling 更通用,例如快 10 倍,占用例如数据库空间减少 3 倍。
您认为 repr/eval...有哪些补偿优势?
顺便说一句,我看到一些答案提到了安全性,但这不是真正的重点:pickling 也是不安全的(评估不受信任的字符串的安全问题可能更明显,但 unpickling 一个不受信任的字符串也是不安全的,尽管更微妙和更黑暗的方式)。
编辑:json 更安全。这是否值得在规模、速度和通用性方面付出巨大代价,是一个值得深思的权衡。大多数情况下不会。
关于python - 为什么我们应该更愿意将序列化数据而不是原始代码存储到数据库中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1685330/