该引用不是关于将XML通常用作存储格式(根据需求可以使用XML),而是用于数据库类型的存储。
当人们谈论的数据库存储,他们通常是指存储系统庞大的数据量,往往在GB或TB级。数据库可能比存储它的服务器上的可用RAM容量大得多。由于没有人一次需要数据库中的所有数据,因此应该优化数据库以快速检索其数据的选择性子集:这就是SELECT
声明的目的,而关系数据库以及NoSQL解决方案可以快速优化其内部存储格式检索此类子集。
但是,XML并不真正符合这些要求。由于其嵌套标签结构,如果不遍历整个文档树(至少直到匹配项),就无法确定某个值在文件中的何处存储(就文件中的字节偏移而言)。关系数据库具有索引,即使使用原始的二进制搜索实现,在索引中查找值也是一次O(log n)查找,然后获取实际值只不过是文件查找(例如fseek(data_file_handle, row_index * row_size)
),即O(1)。在XML文件中,最有效的方法是在文档上运行SAX解析器,在获取实际数据之前进行了大量的读取和查找。除非使用索引,否则您很难获得比O(n)更好的结果,但是随后,您必须为每次插入都重建整个索引(请参见下文)。
插入甚至更糟。关系数据库不保证行顺序,这意味着它们只能追加新行,或覆盖任何标记为“已删除”的行。这非常快:DB只能在周围保留可写位置池;除非池为空,否则从池中获取条目为O(1);最坏的情况是,该池为空,必须创建一个新页面,但这也是O(1)。相比之下,基于XML的数据库将必须将所有内容移动到插入点之后才能腾出空间;这是O(n)。当索引开始起作用时,事情将变得更加有趣:典型的关系数据库索引可以以相对较低的复杂性进行更新,例如O(log n);但是如果要索引XML文件,则每次插入都可能会更改文档中每个值在磁盘上的位置,因此您必须重建整个索引。这也适用于更新,因为更新(例如,元素的文本内容)可以更改其大小,这意味着连续的XML必须移动。如果更新未索引的列,则关系数据库完全不需要接触索引;一个XML数据库将必须为每次更新重建整个索引,以更改更新的XML节点的大小。
这些是最重要的缺点,但还有更多。XML非常冗长,非常适合服务器到服务器的通信,因为它增加了安全性(接收服务器可以对XML执行各种完整性检查,并且如果传输中出现任何错误,则文档不太可能通过验证)。但是,对于大容量存储而言,这是致命的:XML数据具有100%或更多的开销并不罕见(对于SOAP消息之类的开销比率在1000%范围内并不少见),而典型的关系数据库存储方案的表元数据只有恒定的开销,每行只有一点点;关系数据库中的大部分开销都来自固定的列宽。如果您有TB级的数据,出于许多原因,500%的开销根本是不可接受的。