在什么情况下应该序列化数据?什么时候不应该?
我知道序列化是用来把数据类型转换成可以存储的格式,目的是为了像缓存这样的用途。
我更具体想问的是,什么情况下你应该决定存储数据(比如在PHP中使用serialize()
,在Python中使用pickle
模块等等)呢?
假设我们有一个流量很大的网站,在我们的/blog
页面上,我们使用静态内容的xml文件,一个gettext的mo文件,以及从数据库动态生成的内容。
例子 #1:
我们依赖的静态内容文件是en/blog.xml
:
'<content><![CDATA[
<h1>Welcome to my blog!</h1>
<p>Lorem ipsum dolor sit amet..</p>
]]></content>'
我们是否想要序列化这个xml文件并将其存储在缓存中呢?
例子 #2:
我们还有一个动态生成的表单,通常我会认为不需要序列化任何东西,因为它是服务器端生成的动态内容,但我们的表单字段标签是国际化的,用户请求这个页面时选择了西班牙语,因此我们使用一个翻译类来获取存储在mo/csv/xml
格式中的表单字段标签。
contact-us.php
的内容:
<label for="first_name"><?php echo $L->_("First Name");?></label>
<input id="first_name" name="first_name" type="text">
比如“First Name”的消息ID翻译是从应用级翻译文件中提取的,我们解析这个文件并将其存储在一个数组中,这个数组在我们的翻译类里。所以理想情况下,我们的代码不应该在每次请求页面时都解析mo
文件,而是应该在解析完mo文件后序列化整个数组,然后依赖这个序列化的结果吗?
例子 #3:
假设在我们的博客页面上,我们提取最近的5篇博客文章。
$posts = BlogClass->sql('SELECT blog_message, blog_author FROM blog_posts LIMIT 5 ORDER BY blog_date DESC');
我们是否想依赖像memcache这样的东西,并将SQL语句的结果设置为一个键,它会序列化查询的结果吗,还是?
附加问题:
如果有人能提供一些有效或实际的序列化使用/误用的具体例子,那就太好了,比如一个多页面的、非常大的表单,它从数据库中提取信息并存储在会话中,或者任何需要依赖序列化的例子……
2 个回答
在什么情况下你应该决定存储数据(比如在PHP中用serialize(),在Python中用pickle模块等等)呢?
这个问题其实很好回答。各种情况并没有太大关系。
答案是你只有在必须的时候才进行序列化。没有其他情况。
很多API不接受Python对象。当API无法接受Python对象时,你通常可以提供一个字符串。这就是你需要序列化的时刻。
举个例子。你想把一个Python对象保存到持久存储中。可惜的是,一个file
对象不能直接写入Python对象。所以你需要序列化。
再举个例子。你想把一个Python对象发送到另一个进程。你可能在使用套接字、命名管道或者其他方式。这些都是file
对象,而文件对象不能写入Python对象。所以你需要序列化。
这就是你需要序列化的情况。
XML文件就是序列化的DOM树。Python对象是一个DOM树,而XML文件是序列化DOM树的一种方式。我对这个例子不太理解。
表单标签字符串是字符串。它们不需要序列化。国际化(I18N)是和你的应用程序分开处理的。http://docs.python.org/library/i18n.html 我对这个例子不太理解。
这是一个查询。你不需要序列化任何东西。你只需执行查询。结果(原则上)总是在变化,所以任何序列化都是之前的结果,而不是当前的结果,所以你就不需要序列化。
额外补充。如果是一个多页的大表单?你不需要序列化任何东西。你只需在你的网络框架中更新会话。网络框架的会话管理器可能会序列化Python对象,但这就是你使用框架的原因——这样你就不需要关心这些细节。
序列化是用来将Python对象写入文件的。在网络应用中,这种情况很少见。大多数情况下,你是通过SQL写入数据库。
示例 1
概述。
- 生成你的内容页面是否成本太高?
- 反序列化你生成的内容是否成本明显低一些?
如果这两个问题的答案都是“是”,那就值得考虑一下。
示例 2
概述。
- 生成你的内容页面是否成本太高?
- 反序列化你生成的内容是否成本明显低一些?
如果这两个问题的答案都是“是”,那就值得考虑一下。
示例 3
概述。
- 这个查询是否成本太高?
- 从内存缓存中获取数据是否明显更快?
如果这两个问题的答案都是“是”,那就值得考虑一下。
附加内容
我不会因为可以而去序列化我的数据。我需要有理由去做,否则这只是过早的优化。决定是否需要这样做有几个因素。
对序列化数据进行排序或其他操作
这几乎总是个坏主意。例如,如果你把数据库的结果集序列化了,然后需要根据某个字段重新排序,这样做会让自己陷入困境。
消息传递
如果你需要把序列化的数据传递给其他服务或语言,那么选择序列化的方法就非常重要。如果我知道或者认为其他地方可能需要读取这些数据,我会避免使用特定语言的方法进行序列化。JSON通常是跨语言序列化的理想格式。
更新序列化的数据
你必须愿意在数据源更新时重新生成序列化的数据。对序列化数据进行任何复杂的更新将会非常昂贵。
人类可读性
如果你需要轻松读取数据,我建议避免使用特定语言的格式。我推荐使用JSON。
编辑:
我刚刚再次查看了示例3中的查询。这个查询非常简单,你只选择了两个字段,并按日期字段排序。只要表格索引得当,这个查询应该是微不足道的,我不建议把这样的内容缓存到内存中。