SDE空间索引的内部运行机制3

0
分享 2016-03-03
ST_GEOMETRY
ST_GEOMETRY这种存储方式是从ArcSDE9.2开始支持的,但是9.2还是将SDELOB作为默认的存储方式,并没有将其作为默认的存储方式,直到ArcSDE后才开始将其作为默认的存储方式。
在详细介绍ST_GEOMETRY之前先介绍一下Oracle的复合数据类型,从Oracle 9开始,Oracle除了支持常规数据类型,如NUMBER,VARCHAR等,还开始支持复合数据类型,在Oracle中创建复合数据类型非常类似于在C++中创建类,只不过指定这个规则的是Oracle而已,我们自己可以随意的创建复合数据类型,如下面我自己创建了一个Person 的复合数据类型,这个数据类型可以存储个人信息:
CREATE TYPE person_typ AS OBJECT
(
idno NUMBER,
first_name VARCHAR2(20),
last_name VARCHAR2(25),
email VARCHAR2(25),
phone VARCHAR2(20),
MAP

MEMBER FUNCTION get_idno RETURN NUMBER,


MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ));

CREATE TYPE BODY person_typ AS MAP


MEMBER FUNCTION get_idno RETURN NUMBER IS BEGIN RETURN idno;
END;

MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) IS
BEGIN

-- use the PUT_LINE procedure of the DBMS_OUTPUT package to display details


DBMS_OUTPUT.PUT_LINE(TO_CHAR(idno) || ' ' || first_name || ' '|| last_name); DBMS_OUTPUT.PUT_LINE(email || ' ' || phone);END;
END
;
/

从上面的定义上,有成员变量,有成员方法,其格式非常类似于C++中的类。
然后可以创建一个表,其某个字段的类型可以选择person_typ,作为存储类型,如:
CREATE TABLE contacts (
contact person_typ,
contact_date DATE );
INSERT INTO contacts VALUES (
person_typ (65, 'Verna', 'Mills', 'vmills@oracle.com', '1-800-555-4412'),
'24 Jun 2003' );
ST_GEOMETRY也是一个复合存储类型,不同的是它是由ESRI公司自己定义的,用来存储空间数据的复合存储类型,它的定义也是透明的,可以使用下面的命令进行查看:
SQL> desc sde.st_geometry
sde.st_geometry is


NOT FINAL
Name Null? Type
----------------------------------------- -------- ---------------------------
ENTITY NUMBER(38)
NUMPTS NUMBER(38)
MINX FLOAT(64)
MINY FLOAT(64)
MAXX FLOAT(64)
MAXY FLOAT(64)
MINZ FLOAT(64)
MAXZ FLOAT(64)
MINM FLOAT(64)
MAXM FLOAT(64)
AREA FLOAT(64)
LEN FLOAT(64)
SRID NUMBER(38)
POINTS BLOB

METHOD
------
FINAL CONSTRUCTOR FUNCTION ST_GEOMETRY RETURNS SELF AS RESULT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
GEOM_STR CLOB IN
SRID NUMBER IN

METHOD
------
MEMBER FUNCTION ST_AREA RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_LEN RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_LENGTH RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_ENTITY RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_NUMPTS RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MINX RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MAXX RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MINY RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MAXY RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MINM RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MAXM RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MINZ RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_MAXZ RETURNS NUMBER

METHOD
------
MEMBER FUNCTION ST_SRID RETURNS NUMBER

METHOD
------
STATIC FUNCTION GET_RELEASE RETURNS NUMBER

METHOD
------
FINAL CONSTRUCTOR FUNCTION ST_GEOMETRY RETURNS SELF AS RESULT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
X NUMBER IN
Y NUMBER IN
Z NUMBER IN
M NUMBER IN
SRID NUMBER IN

其中红色部分为该复合数据类型的成员变量,其中比较重要的环境变量为POINTS,它的类型为BLOB,该成员变量就是存储空间点串坐标的变量。
同样我们可以通过各种工具来创建包含该数据类型字段的表,如下面是我们用ArcCatalog所创建的FeatureClass cities的表结构:
Oracle数据库:
SQL> desc cities_2
Name Null Type
----------------------------------------- -------- ----------------------------

OBJECTID NOT NULL NUMBER(38)
CITY_NAME NVARCHAR2(30)
GMI_ADMIN NVARCHAR2(7)
ADMIN_NAME NVARCHAR2(42)
FIPS_CNTRY NVARCHAR2(2)
CNTRY_NAME NVARCHAR2(30)
STATUS NVARCHAR2(50)
POP_RANK NUMBER(5)
POP_CLASS NVARCHAR2(22)
PORT_ID NUMBER(5)
LABEL_FLAG NUMBER(5)
SHAPE ST_GEOMETRY
DB2数据库:

[sde@testserver ~]$ db2 describe table sde.test


type name Length Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------



OBJECTID SYSIBM INTEGER 4 0 No



NAME SYSIBM VARCHAR 256 0 Yes
SHAPE DB2GSE ST_MULTIPOLYGON 0 0 Yes
RASTER SYSIBM INTEGER 4 0 Yes


从该表的表结构可以看出,ST_GEOMETRY相对于的SDELOB存储方式已经将B表和F表合而为一了,以前的F表已经作为B表的一个SHAPE字段存在于B表中。
然后再介绍一下ST_GEOMETRY的索引结构:
ST_GEOMETRY存储方式的空间索引实现方式是在数据库层次上实现的,并不是在应用层次上实现的,之所以会这么说,在下面会有相应的介绍。
先介绍一下存储索引信息的位置:
和SDELOB存储方式一样,ST_GEOMETRY的具体的索引信息也是存储S表,该S表的表结构和SDELOB存储的方式一样,在此不重复介绍。
和SDELOB存储方式不同的是,它在数据库中是存在着一个相应的空间索引的定义,我将定义两个字标红的意思是该索引只是定义的一个数据库对象,其内部并不存储任何的数据,真是的索引信息是存储在S表中的,下面的数据为Cities_2表中所有的所有的索引信息:
SQL> select index_name,index_type from user_indexes where table_name='CITIES_2';

INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------

SYS_IL0000092702C00027$$ LOB
R2068_SDE_ROWID_UK NORMAL
A1465_IX1 DOMAIN




在列出的索引中多了一种类型为DOMAIN的索引,该索引为oracle的域索引,实际上就是自定义索引。我们接着查看一下该域索引的定义:
SQL> select dbms_metadata.get_ddl('INDEX','A1465_IX1','SDE') from dual;

DBMS_METADATA.GET_DDL('INDEX','A1465_IX1','SDE')
--------------------------------------------------------------------------------
CREATE INDEX "SDE"."A1465_IX1" ON "SDE"."CITIES_2" ("SHAPE") INDEXTYPE IS "SDE"."ST_SPATIAL_INDEX" PARAMETERS ('ST_GRIDS = 4.3144346983011
T_COMMIT_ROWS = 10000 PCTFREE 0 INITRANS 4')
其中红色位置标出来的是需要注意的,
SHAPE:表示是在SHAPE字段上所建立的索引。
INDEXTYPE:索引的类型,实际上这是一个最关键的对象,在下面进行更详细的介绍
ST_GRIDS:各级网格的大小,因为该图层上我只建立了一级索引,因此在这个例子上只包括一级索引
下面接着看看SDE.ST_SPATIAL_INDEX这个对象在oracle中是如何定义的:
SQL> select dbms_metadata.get_ddl('INDEXTYPE','ST_SPATIAL_INDEX','SDE') from dual;


DBMS_METADATA.GET_DDL('INDEXTYPE','ST_SPATIAL_INDEX','SDE')
--------------------------------------------------------------------------------

CREATE OR REPLACE INDEXTYPE "SDE"."ST_SPATIAL_INDEX" FOR
"SDE"."ST_BUFFER_INTERSECTS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY", NUMBER),
"SDE"."ST_CROSSES" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),
"SDE"."ST_ENVINTERSECTS" ("SDE"."ST_GEOMETRY", NUMBER, NUMBER, NUMBER, NUMBER),
"SDE"."ST_ENVINTERSECTS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),
"SDE"."ST_ENVINTERSECTS" ("SDE"."ST_GEOMETRY", NUMBER, NUMBER, NUMBER, NUMBER,VARCHAR2),
"SDE"."ST_ENVINTERSECTS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY", VARCHAR2),
"SDE"."ST_EQUALS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),
"SDE"."ST_INTERSECTS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),
"SDE"."ST_ORDERINGEQUALS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),


DBMS_METADATA.GET_DDL('INDEXTYPE','ST_SPATIAL_INDEX','SDE')
--------------------------------------------------------------------------------
"SDE"."ST_OVERLAPS" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),
"SDE"."ST_RELATE" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY", VARCHAR2),
"SDE"."ST_TOUCHES" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY"),
"SDE"."ST_WITHIN" ("SDE"."ST_GEOMETRY", "SDE"."ST_GEOMETRY")
USING "SDE"."ST_DOMAIN_METHODS"
WITH LOCAL RANGE PARTITION




其中红色部分为该对象所支持所有的Operator对象,只有列在这里面的操作符对象才有可能用上索引。
绿色部分为实现网格空间索引算法的包。
还剩下最后一个问题,就是为什么说ST_GEOMETRY的空间索引是在数据库层次上实现的而不是在应用层次上实现的。大比例尺下浏览数据的时候,抓取一下后台一下相应的SQL语句如下:
*** 2010-12-16 09:41:09.632
*** ACTION
NAME:() 2010-12-16 09:41:09.631
*** MODULE


NAME:(ArcCatalog.exe) 2010-12-16 09:41:09.631
*** SERVICE NAME:(SYS$USERS) 2010-12-16 09:41:09.631
*** SESSION ID:(152.4487) 2010-12-16 09:41:09.631
=====================
PARSING IN CURSOR #25 len=69 dep=0 uid=68 oct=3 lid=68 tim=1262171552374697 hv=2558560494 ad='8ca78d78'



SELECT table_name, time_last_modified FROM SDE.sde_tables_modified
END OF STMT
EXEC #25:c=0,e=44,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1262171552374688
FETCH #25:c=0,e=52,p=0,cr=1,cu=0,mis=0,r=7,dep=0,og=1,tim=1262171552375294
=====================
PARSING IN CURSOR #46 len=288 dep=0 uid=68 oct=3 lid=68 tim=1262171552380038 hv=1466667998 ad='806b7fd8'



SELECT 1 SHAPE, CITIES_2.OBJECTID, CITIES_2.SHAPE.points,CITIES_2.SHAPE.numpts,CITIES_2.SHAPE.entity,CITIES_2.SHAPE.minx,CITIES_2.SHAPE.miny,CITIES_2.SHAPE.maxx,CITIES_2.SHAPE.maxy,CITIES_2.rowid FROM SDE.CITIES_2 CITIES_2 WHERE SDE.ST_EnvIntersects(CITIES_2.SHAPE,:1,:2,:3,:4) = 1
END OF STMT
EXEC #46:c=1000,e=1162,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1262171552380029
=====================
PARSING IN CURSOR #48 len=158 dep=1 uid=68 oct=3 lid=68 tim=1262171552380494 hv=4131701150 ad='806b5468'



SELECT distinct sp_id FROM SDE.S258_IDX$ WHERE gx >= :1 AND gx <= :2 AND gy >= :3 AND gy <= :4 AND minx <= :e1 AND miny <= :e2 AND maxx >= :e3 AND maxy >= :e4
END OF STMT
EXEC #48:c=0,e=117,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,tim=1262171552380485
FETCH #48:c=3000,e=2679,p=0,cr=18,cu=0,mis=0,r=100,dep=1,og=1,tim=1262171552383304
FETCH #48:c=0,e=177,p=0,cr=0,cu=0,mis=0,r=100,dep=1,og=1,tim=1262171552383632
FETCH #48:c=0,e=185,p=0,cr=0,cu=0,mis=0,r=100,dep=1,og=1,tim=1262171552383946
FETCH #48:c=999,e=189,p=0,cr=0,cu=0,mis=0,r=100,dep=1,og=1,tim=1262171552384262
FETCH #48:c=0,e=184,p=0,cr=0,cu=0,mis=0,r=100,dep=1,og=1,tim=1262171552384574


从上面所执行的SQL中可以看出的确访问了S258_IDX$表,更重要的是和SDELOB存储方式不同的是dep=1,这说明这条SQL并不是由前端应用所提交给数据库,而是数据库自己所执行的,换句话说是因为执行,前一个SQL:
SELECT 1 SHAPE, CITIES_2.OBJECTID, CITIES_2.SHAPE.points,CITIES_2.SHAPE.numpts,CITIES_2.SHAPE.entity,CITIES_2.SHAPE.minx,CITIES_2.SHAPE.miny,CITIES_2.
SHAPE.maxx,CITIES_2.SHAPE.maxy,CITIES_2.rowid FROM SDE.CITIES_2 CITIES_2 WHERE SDE.ST_EnvIntersects(CITIES_2.SHAPE,:1,:2,:3,:4) = 1

而导致Oracle所执行的SQL,所以ST_GEOMETRY的空间索引实现是在数据库层次上实现的。


文章来源:http://blog.csdn.net/liufeng1980423/article/details/6089547

0 个评论

要回复文章请先登录注册