为什么我们应该将序列化数据而不是原始代码存储到DB?

Zhu*_*Tao 2 python database serialization

如果我们有一些应该存储在DB中的代码(数据结构),有人总是建议我们存储序列化数据而不是原始代码字符串.

所以我不太清楚为什么我们应该更喜欢序列化数据.

给一个简单的实例(在python中):

我们有一个字段可以存储python的字典,就像

{ "name" : "BMW", "category":"car", "cost" : "200000"}
Run Code Online (Sandbox Code Playgroud)

所以我们可以使用pickle(python模块)对其进行序列化,然后将pickle数据存储到db字段.

或者我们可以直接将dict字符串存储到DB而无需序列化.

由于我们需要将字符串转换为python数据,因此通过分别使用pickle.loads和exec,两种方法都很容易实现.

那应该是首选的?为什么?是因为exec比pickle慢得多吗?还是其他一些原因?

谢谢.

Ale*_*lli 11

或者我们可以直接将dict字符串存储到DB而无需序列化.

没有"dict字符串"这样的东西.有很多方法可以将字典序列化为字符串; 你可能会想到repr,可能就像eval恢复字典一样(你提到exec,但这简直荒谬:你会执行什么声明......?我认为你可能意味着eval).它们是不同的序列化方法及其权衡,在许多情况下,权衡往往倾向于酸洗(cPickle对于速度,协议-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
Run Code Online (Sandbox Code Playgroud)

...为什么每次序列化像这样的字典时,你想要存储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
Run Code Online (Sandbox Code Playgroud)

...为什么要花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
Run Code Online (Sandbox Code Playgroud)

VS

$ python -c'import cPickle
def f(): pass
d={"x":f}
print d == cPickle.loads(cPickle.dumps(d, -1))'
True
Run Code Online (Sandbox Code Playgroud)

编辑:在往返方面,json甚至不如repr.

因此,比较两种序列化方法(酸洗与repr/eval),我们看到:酸洗方式更为通用,它可以提高10倍,并占用数据库中3倍的空间.

您为repr/eval设想了哪些补偿优势?

顺便说一下,我看到一些答案提到了安全性,但这不是一个真正的观点:酸洗也是不安全的(eval不可信任字符串的安全问题可能更明显,但是对不可信任的字符串进行破坏也是不安全的,尽管以更微妙和更暗的方式).

编辑:json更安全.这是否值得在规模,速度和普遍性方面付出巨大代价,这是一个值得深思的权衡.在大多数情况下,它不会.