5.3 原生xml数据库的数据存储(storing data in a native xml database)
还可以将xml文件中的数据存储在原生xml数据库(native xml database)中。这么做有几个理由。首先,当你的数据是半结构化的数据时。也就是说,它的结构是普通的,但是如果将其映射到关系数据库,结果是要么出现大量空值(null)的字段,要么表格的数量过多,浪费空间或效率低下。虽然半结构化的数据可存储到面向对象的或层次型数据库中,你还可以选择将它以xml文件的形式存储于原生xml数据库。
将数据存储在原生xml数据库中的第二个理由是读出速度。根据xml数据库存储数据的物理方式的不同,数据的读出速度可以做到比关系型数据库[的读取速度]快得多。其原因是,原生xml数据库对整个文件一起进行物理存储,和[表示]文件各个部分的物理(而不是逻辑)指针可采用同一存储策略。这就可以不使用连接(joins)或只使用物理连接读取文件,无论哪种情况都比关系型数据库所用的逻辑联结要快。
以上述销售订单文件为例。在关系型数据库中,它可能被存为四个表格 -- salesorders, items, customers, 和 parts -- 读取文件时需要将这些表格结合起来。在原生xml数据库中,整个文件可被存储在磁盘的一个地方,在读取文件或其片断时只需要一次查找和一次读取操作。关系数据库在读取数据时则需要四次查找以及至少四次读取操作。
这样做的一个明显缺点就是,只有数据的读取顺序和写入磁盘的顺序相同时,才可以提高速度。如果你想要的数据视图不同,比如只想要客户及其订单列表,性能可能比关系数据库更差。所以,如果你的应用中是单个数据视图为主, 为了提高性能,才可以考虑将数据存储到原生xml数据库。
将数据存储在原生xml数据库中的第二个理由是你想利用xml的独有特性,如执行xml查询。由于今天以数据为中心的应用几乎没有这样做的,而且关系数据库正在逐步支持xml查询语言,这个理由越来越不充分。
将数据存储在原生xml数据库中的一个问题是,大多数原生数据库只能以xml[的形式]返回数据。(支持元素和属性到应用程序变量绑定的只是少数)。如果你的应用程序需要另一种数据格式(很有可能),使用数据之前必须先解析xml。对本地的应用程序而言显然是个缺点,而这种前期准备在(比如)odbc中就不存在。对于将xml作为数据载体使用的分布式应用程序而言,这个问题不很严重,因为不管用的是哪种数据库,这种前期工作必须要有。
本节将就在传统数据库中存储xml文件数据的相关问题展开讨论。(有关数据类型和二进制数据存储的讨论同样适用于原生xml数据库)总的说来,你无法选择数据交换软件解决这些问题的方式。然而,你应当明白这些问题确实存在,这样会有助于你选择软件。
如果单纯从字面上讲,xml不支持任何数据类型。除了非解析实体,xml文件中的所有数据都是文本,尽管它可能表示日期或整数等其他类型。一般来说,数据交换软件负责把(xml文件中的)文本转换成(数据库中的)其他数据类型,反之亦然。但是,能够被识别为特定数据类型的文本格式数目很有限,比如某个jdbc驱动程序所支持的。日期看起来最容易出问题,因为它的格式可能非常多。而数字在各种语言中的格式也不尽相同,也有可能出问题。
二进制数据在xml文件中的存储方法一般有两种:非解析实体和base64编码(一种编码方式,将二进制数据映射到us-ascii码的一个子集)。对于关系型数据库,这两种方法都可能产生问题,因为数据库中二进制数据的存取规则非常严格,可能导致软件出错。此外,由于xml标准标记中没有哪个能指明某个元素含有以base64编码的数据,所以软件甚至可能无法识别数据是以base64编码的。最后,与非解析实体或base64编码元素相关的标记是大多数(全部?)数据转换软件在往数据库中存储时所忽略的方面之一。因此,如果二进制数据对你来说很重要,就应确认你所用的软件是否支持它的存取。
在数据库术语中,空数据(null data)意味着没有数据。这和值为0的数字或长度为零的字符串区别非常大。例如,假设你收集到的是气象数据,如果温度计不能工作,则数据库中存储的就是null而不是0,否则情况就完全不同了。
xml也支持这种空数据的概念(通过可选(optional)元素或属性)。如果一个可选元素或属性的值为空,就不会包含在文件内。而在数据库中,值为零长度字符串的属性和空元素并不是null:它们的值为零长度的字符串。
当你将xml文档的结构映射到数据库(或反过来)时,你当特别留意,可选元素类型或[空值]属性会被映射到允许空值的字段(nullable columns),反之亦然。如果不是这样的话,可能会产生插入错误(当转换数据到数据库时)或非法文件错误(从数据库中取出数据时)。
与数据库专业相比,xml社区对null含义的表示法更为自由-- 特别是许多xml用户都认为零长度字符串的属性和空元素是“空(null)”的,所以你应该检查一下你的软件是如何处理这种情况的。有些软件为用户提供了选择,可以定义xml中如何表示"null",以及支持xml schema中的 xsi:null属性。
根据定义,除了某些控制字符,xml文件可包含任何unicode字符。不过,许多数据库对unicode的支持很有限或根本就不支持,而且需要特殊的配置才能处理非ascii字符。如果你的文件包含非ascii字符,要确保你的数据库及数据转换软件对这些字符是否支持及如何支持的。
在数据库中可存为:5.4 数据类型,空值,字符集及其他 (data types, null values, character sets, and all that stuff)
5.4.1 数据类型 data types
5.4.2 二进制数据 (binary data)
5.4.3 空数据 (null data)
5.4.4 字符集 (character sets)
5.4.5 处理指令和注释 (processing instructions and comments)
处理指令和注释并不是xml文档“数据”的一部分,大多数(全部?)数据转换软件都不能处理它们。问题在于这些东西可能出现在xml文档中的任何地方,所以不容易进行基于表格或对象-关系型映射。(一个明显行不通的方案是为这些处理指令和注释建立一个表格,在其他表格加上指向这个表格的外部键(foreign key),每当处理别的表格时,就检查这些表)。所以大多数数据转换软件会简单地忽略它们。如果处理指令和注释对你相当重要,就要检查所用软件对此能否处理及处理方法。或者可以考虑使用原生xml数据库(native xml database)。
5.4.6 对标记的存储 (storing markup)
正如5.1.2 一节所提到的, 有时候需要在数据库中存储混合内容的元素而无须进一步解析。这时, 标记被存储为标记字符(markup is stored with markup characters)。然而,问题出现在如何存储那些不作为标记使用的标记字符。在xml文档中,这些是以 lt, gt, amp, quot 和 apos 实体存储的。在数据库中也可这么做。例如,下面的description: <description>
<b>confusing example:</b> <foo/>
</description>