相同或不同的表
XML数据类型列可以在包含其他关系列的表中创建,也可以在与主表之间具有外键关系的独立表中创建。
在满足下列某个条件时,请在同一个表中创建XML数据类型列:
- 您的应用程序在XML列上执行数据检索,并且不需要XML列上的XML索引。 或者
- 您需要在XML数据类型列上生成XML索引,并且主表的主键与其聚集键相同。有关详细信息,请参阅将XML数据类型列编入索引一节。
在满足下列条件时,请在单独的表中创建XML数据类型列:
- 您需要在XML数据类型列上生成XML索引,但主表的主键与其聚集键不同,或者主表不具有主键,或者主表是一个堆(也就是说,没有聚集键)。如果主表已经存在,则这可能是真的。
- 您不希望表扫描由于表中存在XML列(无论它是存储在行中还是存储在行外,都会占用空间)而降低速度。
XML数据的粒度
XML列中存储的XML数据的粒度对于锁定和更新特性而言至关重要。SQL Server 对XML和非XML数据采用了相同的锁定机制。因此,行级锁定会导致相应行中的所有XML实例被锁定。当粒度比较大时,锁定大型 XML 实例以便进行更新会导致多用户场合下的吞吐量下降。另一方面,严重的分解会丢失对象封装并提高重新组合成本。
对XML实例进行更新会将现有实例替换为更新后的实例,即使只修改单个属性的值。XML数据粒度越大,更新成本就越高。较小的XML实例会产生较高的更新性能。
对于良好的设计而言,重要的是保持数据建模需要与锁定和更新特性之间的平衡。
非类型化、类型化和受约束的XML数据类型
SQL Server 2005 XML数据类型实现了ISO SQL-2003标准XML数据类型。因此,它可以在非类型化XML列中存储格式规范的XML1.0文档以及带有文本节点和任意数量顶级元素的所谓的XML内容片段。系统将检查数据的格式是否规范,不要求将列绑定到XML架构,并且拒绝在扩展意义上格式不规范的数据。对于非类型化XML变量和参数,也是如此。
如果您具有描述XML数据的XML架构,则可以将这些架构与XML列相关联,以便产生类型化 ML。XML架构用于对数据进行有效性验证,在查询和数据修改语句编译过程中执行比非类型化XML更准确的类型检查,以及优化存储和查询处理。
在下列条件下,请使用非类型化XML数据类型:
- 您没有对应于 XML 数据的架构
- 您拥有架构,但不希望服务器对数据进行有效性验证。当应用程序在服务器中存储数据之前执行客户端验证时,或者暂时存储根据架构无效的XML数据时,或者使用在服务器中不受支持的架构组件(例如key/keyref)时,有时会出现这种情况。
在下列条件下,请使用类型化XML数据类型:
- 您拥有对应于XML数据的架构,并且希望服务器按照XML架构对XML数据进行有效性验证。
- 您希望充分利用基于类型信息的存储和查询优化。
- 您希望在查询的编译过程中更充分地利用类型信息。
类型化XML列、参数和变量可以存储XML文档或内容 – 您在声明时必须将它们指定为标志(分别指定为 DOCUMENT或CONTENT)。而且,您必须提供XML架构集合。如果每个XML实例恰好有一个顶级元素,请指定DOCUMENT;否则,请使用CONTENT。查询编译器在查询编译过程的类型检查中使用DOCUMENT标记来推理唯一的顶级元素。
除了将XML列类型化以外,您还可以在类型化或非类型化 XML 数据类型列上使用关系(列或行)约束。在下列条件下,请使用约束:
- 无法在XML架构中表示业务规则。例如,花店的送货地址必须在其营业地点周围50英里范围之内,这可以编写为XML列上的约束。该约束可能涉及到XML数据类型方法。
- 您的约束涉及到表中的其他XML列或非XML列。这方面的一个例子是:强制XML实例中存在的Customer ID(/Customer/@CustId) 与关系CustomerID列中的值匹配。
文档类型定义(DTD)
XML数据类型列、变量和参数可以使用XML架构而不是DTD加以类型化。然而,对于非类型化和类型化XML,都可以使用内联DTD来提供默认值,以便将实体引用替换为它们的扩展形式。
您可以使用第三方工具将DTD转化为XML架构文档,并且将XML架构加载到数据库中。
将XML数据类型列编入索引
可以在XML数据类型列上创建XML索引。这会将该列中XML实例上的所有标记、值和路径编入索引,从而提高查询性能。在下列条件下,您的应用程序可能受益于XML索引:
- 对XML列进行查询在您的工作负荷中很常见。必须考虑数据修改过程中的XML索引维护成本。
- XML值相对较大,而检索的部分相对较小。生成索引可以避免在运行时分析全部数据,并且因为受益于索引查找而提高查询处理的性能。
XML列上的第一个索引是”主XML索引”。通过该索引,可以在XML列上创建三种类型的辅助XML索引,从而提高常见种类的查询的速度,如下节所述。
主XML索引
这会将XML列中的XML实例内部的所有标记、值和路径编入索引。基表(即包含XML列的表)必须在该表的主键上具有聚集索引;主键用于将索引行与基表中的行相关联。从XML列中检索完整的XML实例(例如select *)。查询使用主XML索引,并返回标量值或使用索引本身的XML子树。
示例:创建主XML索引
在我们的多数示例中,都使用带有非类型化XML列的表T (pk INT PRIMARY KEY, xCol XML),这些示例都可以简单地扩展为类型化XML的形式(有关使用类型化XML的信息,请参阅SQL Server 2005联机图书)。为了便于说明,将针对如下所示的XML数据实例描述查询:
<book genre=”security” publicationdate=”2002″ ISBN=”0-7356-1588-2″>
<title>Writing Secure Code</title>
<author>
<first-name>Michael</first-name>
<last-name>Howard</last-name>
</author>
<author>
<first-name>David</first-name>
<last-name>LeBlanc</last-name>
</author>
<price>39.99</price>
</book>
下面的语句在表T的XML列xCol上创建了名为idx_xCol的XML索引:
create PRIMARY XML INDEX idx_xCol on T (xCol)
辅助XML索引
在创建主XML索引之后,您可能希望创建辅助XML索引来提高工作负荷中的不同种类查询的速度。三种类型的辅助XML索引- PATH、PROPERTY和VALUE分别为基于路径的查询、自定义属性管理场合和基于值的查询提供帮助。PATH索引在列中的所有XML实例上,按照文档顺序生成各个XML节点的(path, value) 对的B+树。PROPERTY索引创建各个XML实例中(PK, path, value)对的聚集B+树,其中PK是基表的主键。最后,VALUE索引在XML列中的所有XML实例中,按照文档顺序创建各个节点的(value, path) 对的 B+ 树。
以下是创建上述一个或多个索引的一些准则:
- 如果工作负荷大量使用XML列中的路径表达式,则PATH辅助XML索引可能会加快工作负荷的处理速度。最常见的例子是在T-SQL的where子句中对XML列使用exist()方法。
- 如果您的工作负荷从单独的使用路径表达式的XML实例中检索多个值,则将各个XML实例中的路径聚集到PROPERTY索引中可能会很有用。这种情况通常出现在属性包场合中,此时对象的属性被获取并且其主键值已知。
- 如果您的工作负荷涉及到查询XML实例中的值,而不知道包含这些值的元素或属性名称,则您可能需要创建VALUE索引。这通常发生在子代轴查找中,例如 //author[last-name=”Howard”],其中 元素可以出现在层次结构的任意级别上。这种情况还会发生在”通配符”查询中,例如
/book [@* = “novel”],其中查询将查找具有某个值为 “novel” 的属性的 元素。
示例:基于路径的查找
假设下面的查询在您的工作负荷中很常见:
select pk, xCol
FROM T
where xCol.exist (’/book[@genre = “novel”]’) = 1
路径表达式 /book/@genre和值”novel”对应于PATH索引的键字段。因此,PATH类型的辅助XML索引对于该工作负荷很有用:
create XML INDEX idx_xCol_Path on T (xCol)
USING XML INDEX idx_xCol FOR PATH
示例:获取对象的属性
请考虑下面的查询,它从表T的各个行中检索一本书的属性”genre”、”title”和ISBN:
select xCol.value (’(/book/@genre)[1]’, ’varchar(50)’),
xCol.value (’(/book/title)[1]’, ’varchar(50)’),
xCol.value (’(/book/@ISBN)[1]’, ’varchar(50)’)
FROM T
在这种情况下,属性索引很有用,其创建方式如下所示:
create XML INDEX idx_xCol_Property on T (xCol)
USING XML INDEX idx_xCol FOR PROPERTY
示例:基于值的查询
在以下查询中,子代轴或自身轴 (//) 指定了部分路径,以便基于ISBN值的查找可以因为使用VALUE索引而受益:
select xCol
FROM T
where xCol.exist (’//book[@ISBN = “1-8610-0157-6”]’) = 1
VALUE索引按如下方式创建:
create XML INDEX idx_xCol_Value on T (xCol)
USING XML INDEX idx_xCol FOR VALUE
XML列上的全文索引
您可以在XML列上创建全文索引,从而将XML值的内容编入索引,而忽略XML标记。属性值没有被编入全文索引(因为它们被视为标记的一部分),并且元素标记被用作标记边界。在某些情况下,可以将全文搜索与XML索引用法结合起来:
- 首先,使用SQL全文搜索筛选感兴趣的XML值。
- 接下来,查询这些XML值,这会使用XML列上的XML索引。
示例:将全文搜索与XML查询结合起来
在XML列上创建全文索引之后,以下查询将检查XML值是否在书名中包含单词”custom”:
select *
FROM T
where CONTAINS(xCol,’custom’)
AND xCol.exist(’/book/title/text()[contains(.,”custom”)]’) =1
CONTAINS()方法使用全文索引,将文档中任何地方包含单词”custom”的 XML 值组合为一个子集。exist() 子句确保单词”custom”出现在书名中。
使用CONTAINS()和XQuery contains()的全文搜索具有不同的语义。后者是子字符串匹配,而前者则是使用单词衍生的标记匹配。因此,如果要搜索标题中的字符串 “run”,则 “run”、”runs”和”running” 都将匹配,因为全文CONTAINS()和Xquery contains() 都满足。然而,上述查询不匹配标题中的单词”customizable”。(全文CONTAINS()失败,而 Xquery contains() 被满足)。通常,对于纯粹的子字符串匹配,应该删除全文CONTAINS() 子句。
而且,全文搜索采用单词衍生,而XQuery contains() 是一种字面匹配。这一区别将在下一个示例中阐述。
示例:使用单词衍生对XML值进行全文搜索
通常情况下,不能排除示例:将全文搜索与XML查询结合起来中的XQuery contains()检查。请考虑查询:
select *
FROM T
where CONTAINS(xCol,’run’)
因为使用单词衍生,所以文档中的单词”ran”匹配搜索条件。而且,使用XQuery时不会检查搜索上下文。
在使用被全文索引的AXSD将XML分解到关系列中时,XML视图上的XPath查询不会对基础表执行全文搜索。
属性提升
如果主要是对少量元素和属性值进行查询(例如,基于客户ID查找客户,即指定了/Customer/@CustId的值),您可能希望将这些数量提升到关系列中。当检索了整个XML实例,但只对一小部分XML数据进行查询时,这将很有用。在XML列上创建XML索引是没有必要的;相反,可以将被提升的列编入索引。必须编写查询以使用提升的列(即,查询优化器不会将对XML列的查询重新定向到提升的列)。
提升的列可以是同一表中的计算列,也可以是表中单独的、用户维护的列。当从各个XML实例中提升唯一值(即单值属性)时,这已足够。然而,对于多值属性,您必须为该属性创建单独的表,如下所述。
基于XML数据类型的计算列
可以使用能够激活XML数据类型方法的用户定义函数(UDF)来创建计算列。计算列的类型可以是任何SQL类型,包括XML。以下示例说明了这一点。
示例:基于XML数据类型方法的计算列
为书籍的 ISBN 创建用户定义的函数:
create FUNCTION udf_get_book_ISBN (@xData xml)
RETURNS varchar(20)
BEGIN
DECLARE @ISBN varchar(20)
select @ISBN = @xData.value(’/book[1]/@ISBN’, ’varchar(20)’)
RETURN @ISBN
END
为 ISBN 向表中添加一个计算列:
alter TABLE T
ADD ISBN AS dbo.udf_get_book_ISBN(xCol)
可以用通常的方式将计算列编入索引。
示例:基于XML数据类型方法的计算列上的查询
要获取其ISBN为 0-7356-1588-2 的 ,可以改写XML列上的查询
select xCol
FROM T
where xCol.exist (’/book[@ISBN = “0-7356-1588-2”]’) =1
以使用计算列,如下所示:
select xCol
FROM T
where ISBN = ’0-7356-1588-2’
可以创建一个用户定义的函数,返回XML数据类型和使用该UDF的计算列。然而,无法在计算的XML列上创建XML索引。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
作者
相关推荐
-
数据库设计需做好前期工作 Agile方法不适合
有很多企业认为数据建模以及设计良好的数据库是浪费时间的工作,对此专家的回答很直接:决不能忽视数据库设计过程。
-
SAP HANA数据建模秘籍
SAP HANA是一个全新的数据库平台,它提供了全新的数据建模方式,使得传统关系型数据库管理系统(RDBMS)得到了进一步的扩展。
-
介绍PostgreSQL的数组类型
PostgreSQL 有很多丰富的开箱即用的数据类型,从标准的数字数据类型、到几何类型,甚至网络数据类型等等。
-
Redis sds数据结构实现分析
sds(Simple Dynamic Strings)是Redis中最基本的底层数据结构, 它既是Redis的String类型的底层实现,也是实现Hash、List和Set等复合类型的基石。