示例:使用R-Tree访问方法的函数索引
在本例中,我们将向您展示如何创建使用 R-Tree 访问方法的函数索引。R-Tree数据结构可以保存有关多维数据的信息,并用于有关空间或地理数据的索引。这类索引有助于改善针对空间数据的查询的性能。
要理解本示例,需要熟悉 IDS DataBlade 技术。具体来说,您应该能够安装和配置所使用的 Spatial DataBlade。有关 DataBlade 的详细信息,请参考 IBM Informix Spatial DataBlade 用户指南。
本例使用的数据包括一些城市的地理数据和 Oregon 州的海啸影响范围。本文下载部分没有提供这些地理数据,但是可以通过 Oregon Geospatial Enterprise Office 网站 自由获取。可从该站点下载 City Limits 2007 和 Tsunami Inundation Line 数据集。
假设您希望查找即将受海啸影响的城市。为此,发出一个空间数据查询,搜索其中心包含在海啸线内的所有城市。要满足这个查询,必须计算地理城市中心,因此,需要创建一个函数索引来计算这个值。由于涉及到空间数据,您需要为这个索引指定 R-Tree 访问方法。
下面列出了R-Tree函数索引的一些有趣特性:
它们不仅是针对相交区域的索引;叶页(leaf page)面保存数据对象本身。R-Tree具有高度上的平稳性:
-
从根页面到任何叶页面的路径均穿过相同数量的层。
-
所有 leave 节点都位于同一级别。
设置
本例中使用的空间函数来自Spatial DataBlade。因此,创建和使用索引不需要编写额外的代码。
该示例针对运行在 64 位 Linux x86 上的 IDS version 11.10 进行了测试。可针对不同平台对指令进行相应修改。
设置以下环境变量:
INFORMIXDIR the location of your IDS installation PATH add $INFORMIXDIR/bin add $INFORMIXDIR/extend/<spatialDataBladeDir>/bin (see below) |
安装Spatial DataBlade。安装指导可从 IDS 11.10 信息中心获得(参考本文末尾的链接)。
下面的指令假设您已经在默认位置安装好了 Spatial DataBlade version 8.21: $INFORMIXDIR/extend/spatial.8.21.xC1,其中 ‘x’ 表示特定于平台的字母。对于 64 位 Linux x86,默认位置为 $INFORMIXDIR/extend/spatial.8.21.FC1。可根据您的环境对指令作出相应修改。
为空间数据创建 sbspace。注意:sbspace 名必须与 ONCONFIG 文件中的 SYSSBSPACENAME 值匹配。本例假设 sbspace 名为 syssbspace。
在与根dbspace相同的目录中创建名为 syssbspace 的空文件(ONCONFIG 文件中 ROOTPATH 的值指定根dbspace的名称和位置)。
将文件所有权改为informix:informix。 将文件权限改为mode 660。
以用户informix的身份,创建sbspace:
onspaces -c -S syssbspace -p <fullpath>/syssbspace -o 0 -s 100000 | 创建您的数据库。
dbaccess - - create database spatialdb; | 注册 Spatial DataBlade。
使用 blademgr 实用工具注册 Spatial DataBlade。Spatial DataBlade 依赖于 R-Tree DataBlade,后者由 IDS 自动附带。因此,必须同时向您的数据库注册这两个 DataBlade。
blademgr register ifxrltree.2.00 spatialdb register spatial.8.21.FC1 spatialdb list spatialdb DataBlade modules registered in database spatialdb: ifxrltree.2.00 spatial.8.21.FC1 | 加载空间数据。
从City Limits 2007和Tsunami Inundation Line下载中提取文件,并分别保存在两个目录中,即citylim_2007和tsunami:
ls citylim_2007 citylim_2007.dbf citylim_2007.prj citylim_2007.sbn citylim_2007.sbx citylim_2007.shp citylim_2007.shp.xml citylim_2007.shx ls tsunami PRJdevelopment.pdf tsunami.dbf tsunami.html tsunami.pdf tsunami.prj tsunami.shp tsunami.shp.xml tsunami.shx |
注意:在 UNIX 上,数据文件名称区分大小写,而且必须为小写。这是 Shapefile 数据的要求。如果文件名不正确,那么 loadshp 实用工具将报告错误,指出它无法找到数据文件。
关于如何正确配置投影数据超出本文讨论的范围。如果没有正确配置,loadshp 实用工具在尝试处理投影信息时将返回错误,因此,隐藏或删除扩展名为 'prj' 的文件:
rm citylim_2007/citylim_2007.prj rm tsunami/tsunami.prj | 使用Spatial DataBlade附带的loadshp实用工具将数据加载到 IDS 中。该实用工具位于 $INFORMIXDIR/extend/spatial.8.21.FC1/bin 中。 loadshp 创建了两个表:cities 和 tsunami,并将空间数据分别加载到 citylim 和 inundation 列中。
$INFORMIXDIDR/extend/spatial.8.21.FC1/bin/loadshp -o create -D spatialdb2 \ -l cities,citylim -f <fullpath>/citylim_2007 $INFORMIXDIDR/extend/spatial.8.21.FC1/bin/loadshp -o create -D spatialdb2 \ -l tsunami,inundation -f <fullpath>/tsunami |
查询
发出查询。在这个查询中,
st_intersects、st_centroid 和 st_envelope 由 Spatial DataBlade 提供 st_envelope 计算每条海啸线的边界,返回类型 st_multilinestring st_centroid 计算每个城市的中心,返回类型 st_multipolygon st_intersects 可确定两种结构是否相互交叉 这次没有定义函数索引。
dbaccess spatialdb - set explain on; select city_name from cities, tsunami where st_intersects( st_centroid( citylim ), st_envelope( inundation ) ); city_name Astoria Bandon Bay City Brookings Cannon Beach Cave Junction Coos Bay Coquille Depoe Bay Dunes City Elkton Falls City Florence Garibaldi Gearhart Glendale Gold Beach Grants Pass Lakeside Lincoln City Manzanita Myrtle Point Nehalem Newport North Bend Port Orford Powers Reedsport Riddle Rockaway Beach Seaside Siletz Tillamook Toledo Waldport Warrenton Wheeler Willamina Winston Yachats 40 row(s) retrieved. |
检查SQL EXPLAIN 输出。该查询计划显示了全表扫描。针对每一个元组(tuple)执行 st_centroid() 计算。
QUERY: ------ select city_name from cities, tsunami where st_intersects( st_centroid( citylim ), st_envelope( inundation ) ) Estimated Cost: 25671 Estimated # of Rows Returned: 7018 1) <owner>.tsunami: SEQUENTIAL SCAN <== Full Table Scan 2) <owner>.cities: SEQUENTIAL SCAN <== Full Table Scan Filters: informix.st_intersects(informix.st_centroid(<owner>.cities.citylim ), |--10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| informix.st_envelope(<owner>.tsunami.inundation )) NESTED LOOP JOIN UDRs in query: -------------- UDR id : 662 UDR name: st_intersects UDR id : 626 UDR name: st_envelope UDR id : 567 UDR name: st_centroid |
创建函数索引计算城市中心。
dbaccess spatialdb - create index citycenterindex on cities( st_centroid( citylim ) st_geometry_ops ) using rtree; |
有关这个索引,需注意以下几点:
指定 R-Tree 访问方法。 st_centroid() 计算城市中心。 st_geometry_ops 指定操作符类。 将操作符类与访问方法结合使用,可以指定创建索引和优化查询时使用的操作符。操作符类通常为一组函数。对于 Spatial DataBlade,st_geometry_ops 类由以下函数组成:
ST_Contains() ST_Crosses() ST_Equals() SE_EnvelopesIntersect() ST_Intersects() SE_Nearest() SE_NearestBbox() ST_Overlaps() ST_Touches() ST_Within() | 执行相同的查询。
dbaccess spatialdb - select city_name from cities, tsunami where st_intersects( st_centroid( citylim ), st_envelope( inundation ) ); |
注意:当索引表达式被用于关系表达式,或作为某个操作符类函数的参数时,查询优化器将考虑使用函数索引。由于 st_centroid() 是索引 st_geometry_ops 中指定的操作符类的成员,优化器在生成查询计划时将考虑使用索引。
注意:优化器不会对下面这个查询使用函数索引。这是因为 st_distance() 不属于 st_geometry_ops() 操作符类。
select city_name from cities, tsunami where st_distance( st_centroid( citylim ), inundation ) < 5280; | 检查 SQL EXPLAIN 输出。该查询计划显示索引扫描使用了函数索引。
注意:查询优化器只有在表统计信息保持最新的情况下使用 R-Tree 索引。这意味着您应该在创建索引之前加载数据,或者在加载数据之后更新表的统计信息。
QUERY: ------ select city_name from cities, tsunami where st_intersects( st_centroid( citylim ), st_envelope( inundation ) ) Estimated Cost: 12920 Estimated # of Rows Returned: 7018 1) <owner>.tsunami: SEQUENTIAL SCAN 2) <owner>.cities: INDEX PATH <== Index Scan (1) VII Index Keys: informix.st_centroid(citylim) (Serial, fragments: ALL) VII Index Filter: informix.st_intersects(informix.st_centroid(<owner>.cities.citylim), informix.st_envelope(<owner>.tsunami.inundation )) NESTED LOOP JOIN UDRs in query: -------------- UDR id : 662 UDR name: st_intersects UDR id : 626 UDR name: st_envelope UDR id : 567 UDR name: st_centroid UDR id : 567 UDR name: st_centroid | 结束语
函数索引是一种强大的性能调优工具。通过减少执行查询时需要检索的元组(tuple)的数量,以及减少查询所需的计算,函数索引能够显着改善性能。
除大型对象外,函数索引可以返回任何标准SQL类型。同样,函数索引还可以返回用户定义的类型。函数索引可以指定各种不同的访问方法,包括 B-Tree、R-Tree 和用户定义的访问方法。
函数索引的存储和维护成本较高。您应该对系统进行成本收益分析,并只在能保证获益的情况下创建函数索引。如果数据大小较小,或者索引对于数据库查询的性能改善帮助不大,则不适合使用函数索引。
本文提供了一些有关函数索引的示例。希望我们介绍的这些创建和使用函数索引的方法能够帮助您改善查询搜索的性能。
如何在Informix中创建并使用函数索引(三)
|