QQ在线服务: 风舞残阳风舞残阳 年满19岁年满19岁 小罗小罗 晴天晴天 心雨心雨 叮叮肉叮叮肉 小周小周 小童小童 小破孩小破孩 遥望当年遥望当年

用户导购指南

水货IBM笔记本电脑报价

行货IBM笔记本电脑报价

IBM服务器报价

IBM笔记本电脑配件报价

本周水货IBM笔记本电脑特价

IBM笔记本电脑驱动下载

水货IBM笔记本电脑验机流程

水货IBM笔记本电脑保修政策

IBM笔记本电脑FRU查询

IBM笔记本电脑常见问题

IBM笔记本电脑使用手册

笔记本电脑验机软件

论坛积分使用说明

水货IBM笔记本电脑异地购机流程

笔记本电脑购机经历及现场

贵宾申请入口

贵宾用户FTP入口

查看笔记本配置

水货APPLE苹果笔记本电脑报价

 
发新话题
打印

DB2 V9.1 XML数据索引简介

DB2 V9.1 XML数据索引简介

供稿人:毕永军

本文简单介绍了XML数据索引的基本概念,并通过一些例子讲解了如何为XML数据建立合适的索引以提高查询效率。
DB2 从版本9.1开始,提供了对XML数据的内置支持,你不仅可以方便地存储XML,而且可以方便快捷地访问XML文档中的元素和属性。为了提高对于XML字段查询的效率,DB2提供了在XML字段上建立索引的功能
关系型数据表的索引会包含一个或多个数据列,与传统的关系型数据表的索引不同。XML索引会包含XML字段中的元素或者属性,建立这个索引时需要用到XML的模式表达式来唯一标识一个元素或者属性。创建一个索引后,可以允许我们访问文档内部的节点,而不是必须访问整个文档。
对于一个XML字段,我们可以允许建立多个索引。在XML字段上建立索引使用CREATE INDEX语句,删除索引使用DROP INDEX语句。
下面我们看一个创建索引的例子。
假设我们有一个表companyinfo,有两个列,一个是公司的ID,另外一个是companydocs,是一个XML列,建表语句如下:

CREATE TABLE companyinfo (ID INT NOT NULL PRIMARY KEY, companydocs XML)

我们有两条记录:ID分别为1 和2, 其中companydocs列的内容如下:
公司1的信息:
<company name="Company1">
<emp id="31201" salary="60000" gender="Female">
<name>
<first>Laura</first>
<last>Brown</last>
</name>
<dept id="M25">
Finance
</dept>
</emp>
</company>

公司2的信息:
<company name="Company2">
<emp id="31664" salary="60000" gender="Male">
<name>
<first>Chris</first>
<last>Murphy</last>
</name>
<dept id="M55">
Marketing
</dept>
</emp>
<emp id="42366" salary="50000" gender="Female">
<name>
<first>Nicole</first>
? Copyright IBM Corp. 2006 87
<last>Murphy</last>
</name>
<dept id="K55">
Sales
</dept>
</emp>
</company>

我们有很多查询都是通过职员标识来查询职员信息,我们可以通过建立如下的索引提高查询效率:
CREATE INDEX empindex on companyinfo(companydocs)
GENERATE KEY USING XMLPATTERN '/company/emp/@id'
AS SQL DOUBLE

第一行语句指定我们在companyinfo表中companydocs字段建立索引,第二行语句通过使用XML模式指定了为XML文档中的职员ID属性建立索引,第三行指定将建立索引的职员标识保存为DOUBLE数据类型。
下面我们看一下XML模式表达式,XML模式表达式和XQuery语言中定义的XPath路径表达式类似,但是XML模式表达式只支持一部分XQuery语句。
XML模式表达式以斜线“/"分割,在分割的每一部分,我们会选择child::、@、attribute::、descendant::、self::、descendant-or-self::前置标志符,后面跟一个XML名称或者XML类型。如果我们没有指定前置标志符,我们会默认使用child::标志符。其中@是attribute::的简写形式。//是/descendant-or-self::/的简写形式。下面我们看几个例子:
1. CREATE INDEX empindex on companyinfo(companydocs)
GENERATE KEY USING XMLPATTERN '/company/emp/@id' AS SQL DOUBLE
2. CREATE INDEX empindex on companyinfo(companydocs)
GENERATE KEY USING XMLPATTERN '/child::company/child::emp/ attribute::id' AS SQL DOUBLE
3. CREATE INDEX idindex on companyinfo(companydocs)
GENERATE KEY USING XMLPATTERN '//@id' AS SQL DOUBLE
4. CREATE INDEX idindex on companyinfo(companydocs)
GENERATE KEY USING XMLPATTERN '/descendant-or-self::node()/ attribute::id' AS SQL DOUBLE
5. CREATE INDEX empindex on companyinfo(companydocs)
GENERATE KEY USING XMLPATTERN '/company/emp/name/last/text()' AS SQL VARCHAR(25)
上述创建索引的语句中,第一个语句和第二个语句是同义的,都是在职员ID这个属性上创建索引。第三个语句和第四个语句也是同义的,是为文档中所有的ID属性创建索引。第5个语句是为文档中的last元素创建索引,其中最后的text()指明为这个节点的文本创建索引。
注意在第三个语句和第四个语句为文档中的所有id属性建立索引。在上面的例子中,dept和emp元素都有id属性,所以dept和emp元素的id都会存放在索引中。
下面我们通过执行一些查询来查看XQuery的执行计划,以及如何使用我们创建的索引。请看下面的查询语句:
SELECT XMLQUERY(
'for $d in $doc/company/emp/name
return <name>{$d/last}</name>'
passing companydocs as "doc")
FROM companyinfo as c
WHERE XMLEXISTS(
'$i/company/emp/dept[@id="M25"]'
passing c.companydocs as "i")
该查询语句返回属于部门ID为M25的雇员的名字。在部门ID上没有创建索引之前,我们可以得到如图1所示的存取计划,我们可以看到整个查询的代价是40.68,在查询中我们只用到了XSCAN,即对于XML文档的扫描。
图 1 没有使用索引的查询计划


优化后的语句如下所示:
SELECT Q9.$C0
FROM $INTERNAL_LET$ ((TABLE ($INTERNAL_XPATH$ ('($INTERNAL_XMLTOXML_NIEO$(Q10.COMPANYDOCS))/company/emp/(dept[(@id
= "M25")])(:-->$C0:)')) ) AS Q1),
(SELECT Q8.$C0
FROM
(SELECT $INTERNAL_LET-AGG$(Q7.$C0)
FROM
(SELECT $INTERNAL_XMLTOXML_NIEO$(Q6.$C0)
FROM
(SELECT $INTERNAL_XMLELEMENT$(elemNullAndBinaryOptions,
$INTERNAL_QNAME$(NULL, NULL, name), $INTERNAL_XMLNAMESPACES$((''),
('')), Q5.$C0)
FROM
(SELECT 1
FROM (VALUES 1) AS Q2) AS Q3, $INTERNAL_FOR$ ((TABLE
($INTERNAL_XPATH$ ('($INTERNAL_XMLTOXML_NIEO$(Q10.COMPANYDOCS))/company/emp/(name)(:-->$C0:)'))
) AS Q4), $INTERNAL_LET$ ((TABLE ($INTERNAL_XPATH$
('Q4.$C0/(last)(:-->$C0:)')) ) AS Q5)) AS Q6) AS
Q7) AS Q8) AS Q9, BIYJ.COMPANYINFO AS Q10
WHERE fn:exists(Q1.$C0)
从优化后的语句我们可以看出,DB2在处理XQuery时,会将一些XML模式表达式重写为数据表的形式进行查询的各种操作。

此时我们在dept的id属性上建立索引,语句如下:
CREATE INDEX DEPTINDEX ON COMPANYINFO(COMPANYDOCS) GENERATE KEY USING XMLPATTERN '/company/emp/dept/@id' AS SQL VARCHAR(10) PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COLLECT STATISTICS

然后我们再次说明上面的查询语句,可以得到如图 2所示的访问存取计划,从中我们可以看到,整个查询的代价降为33.15,同时我们看到在查询中我们使用到了XISCAN,使用到的索引正是我们刚刚创建的DEPTINDEX。


图 2 使用了索引的查询计划
XML数据建立索引时会同时创建两个B型树索引,逻辑索引和物理索引。逻辑索引包含CREATE INDEX语句所指定的XML模式信息。物理索引具有DB2生成的键列来支持逻辑索引,并包含已建立索引的文档值。我们只能操作逻辑索引,物理索引在创建或者删除逻辑索引的时候透明地创建或者删除。我们没有提供操作物理索引的任何接口。
但是物理索引和逻辑索引都在SYSCAT.INDEXES目录视图中,你可以查看物理索引和逻辑索引。如对于我们的例子表companyinfo,我们可以通过下面的语句查询我们创建的逻辑索引和物理索引:

SELECT INDNAME,IID,TABNAME,INDEXTYPE FROM SYSCAT.INDEXES WHERE TABNAME='COMPANYINFO'

输出如下所示:
INDNAME IID TABNAME INDEXTYPE
SQL060926152915060 1 COMPANYINFO XRGN
SQL060926152916320 2 COMPANYINFO XPTH
SQL060926152916460 3 COMPANYINFO REG
EMPINDEX 4 COMPANYINFO XVIL
SQL060926153514190 5 COMPANYINFO XVIP
DEPTINDEX 6 COMPANYINFO XVIL
SQL060926170617910 7 COMPANYINFO XVIP
我们可以看到我们建表时的主键索引类型为REG(常规索引),在XML列上创建的两个索引EMPINDEX和DEPTINDEX的类型为XVIL,表明是逻辑索引,同时每一个索引后面都有一个类型为XVIP的物理索引,名字是系统自动命名的。
我们注意到除了这几个索引外,还有两个索引,类型分别是XRGN和XPTH,这两种索引分别是区域索引和路径索引。 XML路径索引记录存储在XML列中XML文档的所有唯一路径。XML区域索引记录一个XML列在内部保存的区域。所谓区域,就是在一个数据页上保存的多个节点的集合。因为所有的节点都是保存在数据页上的,所以使用比较大的页面大小,可以较少区域索引的大小,从而可能提高性能。区域索引和路径索引都是在创建表的时候自动创建的,仅供DB2内部使用。DB2没有提供访问这两种索引的任何接口。

参考文献:
1、 DB2手册《XML Guide》:
http://www-306.ibm.com/software/data/db2/udb/support/manualsv9.html
2、《XQeury Reference》:
http://www-306.ibm.com/software/data/db2/udb/support/manualsv9.html

(※本文搜集自:重庆未来科技 http://www.wlkj.net 重庆IBM笔记本电脑、重庆IBM水货笔记本电脑、重庆苹果笔记本电脑、重庆IBM服务器专卖)
QQ:99721343 MSN:lichuntian@163.com
手机:13308323317

TOP

发新话题