2.2.1各种矢量数据存储类型的空间索引的实现方式
ArcSDE从开始到现在主要支持以下几种存储类型:
存储类型 |
数据库 |
SDELOB |
Oracle,SQLServer,DB2 |
ST_GEOMETRY |
Oracle,DB2,PostgresQL,Informix |
SDO_GEOMETRY |
Oracle |
2.2.1.1 SDELOB
SDELOB是ArcSDE最先支持的也是最老的一种存储方式,这种存储方式类似于SHP文件的存储方式,它将属性数据和空间数据分别存储在两张表中,用ArcGIS的专业术语这两张表分别称作Business表和F表,其中Business表中存储属性数据,其简称B表,F表存储的是空间数据,至于数据库设计人员为什么将空间数据存储在以F打头的表中就不得而知了,如果是我设计,我可能把表名设计成以DATA打头。下图为抓取的B表和F表的表结构:
B表:
1: SQL > desc cities_1
2: Name Null ? Type
3: ----------------------------------------- -------- ----------------------------
4: OBJECTID NOT NULL NUMBER(38)
5:
CITY_NAME NVARCHAR2(30)
6:
GMI_ADMIN NVARCHAR2(7)
7:
ADMIN_NAME NVARCHAR2(42)
8:
FIPS_CNTRY NVARCHAR2(2)
9:
CNTRY_NAME NVARCHAR2(30)
10:
STATUS NVARCHAR2(50)
11:
POP_RANK NUMBER(5)
12:
POP_CLASS NVARCHAR2(22)
13:
PORT_ID NUMBER(5)
14:
LABEL_FLAG NUMBER(5)
15:
SHAPE NUMBER(38)
F表:
1: SQL > desc f1464
2: Name Null ? Type
3: ----------------------------------------- -------- ----------------------------
4: FID NOT NULL NUMBER(38)
5: NUMOFPTS NOT NULL NUMBER(38)
6: ENTITY NOT NULL NUMBER(38)
7: EMINX NOT NULL FLOAT (64)
8: EMINY NOT NULL FLOAT (64)
9: EMAXX NOT NULL FLOAT (64)
10: EMAXY NOT NULL FLOAT (64)
11: EMINZ FLOAT (64)
12: EMAXZ FLOAT (64)
13: MIN_MEASURE FLOAT (64)
14: MAX_MEASURE FLOAT (64)
15: AREA NOT NULL FLOAT (64)
16: LEN NOT NULL FLOAT (64)
17: POINTS BLOB
两个表是通过B表的SHAPE的字段和F表的FID字段关联起来,在此也引出一个常见的问题,有很多的人发出以下的疑问:
B表的SHAPE字段的类型是NUMBER,这个数据怎么来存储空间数据呢?
从上面的介绍中可以看出来,B表的SHAPE字段并没有存储空间数据,而只是指向空间数据表的一个索引,实际的数据是存储在F表的POINTS字段中,该字段的类型是BLOB。
对于SDELOB这种存储方式也是有空间索引,只是这个空间索引并不是在数据库层次上实现的,而是在应用层次上实现的。之所以这么说,是因为,在对使用SDELOB方式存储的两张表上查不到任何的空间索引,如下图:
B表上的索引:
1: SQL > select index_name,index_type from user_indexes where table_name='CITIES_1' ;
2:
3:
INDEX_NAME INDEX_TYPE
4: ------------------------------ ---------------------------
5:
A1464_IX1 NORMAL
6:
R2067_SDE_ROWID_UK NORMAL
两个索引都是Btree索引
F表的索引:
1: SQL > select index_name,index_type from user_indexes where table_name='F1464' ;
2:
3:
INDEX_NAME INDEX_TYPE
4: ------------------------------ ---------------------------
5:
SYS_IL0000092600C00014$$ LOB
6:
F1464_UK1 NORMAL
F表存在一个LOB索引和一个B-TREE索引, LOB索引从名称上能看出来是Oracle内部对BLOB字段所创建的自己维护的索引,并不是用户自己创建的,不是空间索引。
从上面的图例中可以看出来,在数据库的层面上并没有空间索引。
可能很多人并不理解在应用层面上实现的空间索引,下面来详细的解析这个问题,
先说一下索引信息的存储信息:
相信很多人都听说在ArcSDE中存在着S表,S实际上是Sptail Index Table单词的第一个字母,实际上这张表中存储的就是索引信息,以下为该表的数据结构:
1: SQL > desc s244_idx$
2: Name Null ? Type
3: ----------------------------------------- -------- ----------------------------
4: GX NOT NULL NUMBER(38)
5: GY NOT NULL NUMBER(38)
6: MINX NOT NULL NUMBER(38)
7: MINY NOT NULL NUMBER(38)
8: MAXX NOT NULL NUMBER(38)
9: MAXY NOT NULL NUMBER(38)
10: SP_ID NOT NULL ROWID
红色部分就是ROWID,我在索引的基本原理提到过每个索引都会记录表记录的ROWID,在此得到了验证。
另外这张表也并不是Oracle的heap表,而是一个索引表,也就是这张表本身就是按照索引的顺序存储的,该表的具体定义可以见下图:
1: SQL > select dbms_metadata.get_ddl('TABLE' ,'S244_IDX$' ,'SDE' ) from dual;
2:
3: DBMS_METADATA.GET_DDL('TABLE' ,'S244_IDX$' ,'SDE' )
4: --------------------------------------------------------------------------------
5:
6: CREATE TABLE "SDE"."S244_IDX$"
7:
( "GX" NUMBER(*,0),
8:
"GY" NUMBER(*,0),
9:
"MINX" NUMBER(*,0),
10:
"MINY" NUMBER(*,0),
11:
"MAXX" NUMBER(*,0),
12:
"MAXY" NUMBER(*,0),
13:
"SP_ID" ROWID,
14: CONSTRAINT "S244$_IX1" PRIMARY KEY ("GX", "GY", "MAXX", "MAXY", "MINX", "MINY"
15:
E
16:
17: DBMS_METADATA.GET_DDL('TABLE' ,'S244_IDX$' ,'SDE' )
18: --------------------------------------------------------------------------------
19: ) ORGANIZATION INDEX NOCOMPRESS PCTFREE 0 INITRANS 4 MAXTRANS 255 LOGGING
20: STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
21: PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT )
22:
TABLESPACE "SDE"
23:
PCTTHRESHOLD 5
24:
MONITORING
再解析一下应用层次上实现的意思:
在使用ArcGIS的前端软件,如Desktop, ArcGIS Server的时候,进行地图浏览的时候,尤其是在大比例尺下浏览的时候, 前端软件所提交的SQL语句是S表和F表联合查询的语句,相当于先从S表中过滤出满足条件的ROWID,然后再根据ROWID到F表中快速查到相关的记录,因此这种空间索引的实现方式是在ArcGIS的前端应用软件中实现的。
以下所摘取的是使用ArcMap浏览数据的时候所抓取的Oracle后台所执行的SQL语句。
1:
/opt/oracle/admin/test/udump/test_ora_15720.trc
2:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
3:
With the Partitioning, OLAP, Data Mining and Real Application Testing options
4:
ORACLE_HOME = /opt/oracle
5:
System name: Linux
6:
Node name: lstest
7:
Release: 2.6.18-194.el5
8:
Version: #1 SMP Tue Mar 16 21:52:39 EDT 2010
9:
Machine: x86_64
10:
Instance name: test
11: Redo thread mounted by this instance: 1
12:
Oracle process number: 15
13:
Unix process pid: 15720, image: oracle@lstest
14:
15:
*** 2010-12-14 10:25:56.311
16:
*** ACTION NAME:() 2010-12-14 10:25:56.310
17:
*** MODULE NAME:(ArcCatalog.exe) 2010-12-14 10:25:56.310
18:
*** SERVICE NAME:(SYS$USERS) 2010-12-14 10:25:56.310
19:
*** SESSION ID:(136.314) 2010-12-14 10:25:56.310
20:
BINDS #25:
21:
=====================
22: PARSING IN CURSOR #25 len=69 dep=0 uid=68 oct=3 lid=68 tim=1262005426085287 hv=2558560494 ad='8ca78d78'
23: SELECT table_name, time_last_modified FROM SDE.sde_tables_modified
24:
END OF STMT
25:
EXEC #25:c=0,e=546,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1262005426085278
26: WAIT #25: nam='SQL*Net message to client' ela= 3 driver id=1413697536 #bytes=1 p3=0 obj#=92612 tim=1262005426085433
27:
FETCH #25:c=0,e=117,p=0,cr=1,cu=0,mis=0,r=7,dep=0,og=1,tim=1262005426085510
28:
=====================
29: PARSING IN CURSOR #45 len=443 dep=0 uid=68 oct=3 lid=68 tim=1262005426089015 hv=2026582214 ad='83d2c968'
30: SELECT /*+ INDEX(SHAPE F1464_UK1) */ S_.eminx,S_.eminy,S_.emaxx,S_.emaxy ,SHAPE.fid,SHAPE.numofpts,SHAPE.entity,SHAPE.points,SHAPE.rowid FROM (SELECT /*+ INDEX(SP_ S1464_IX1) */ DISTINCT
31:
sp_fid, eminx, eminy, emaxx, emaxy FROM SDE.S1464 SP_ WHERE SP_.gx >= :1 AND SP_.gx <= :2 AND SP_.gy >= :3 AND
32:
SP_.gy <= :4 AND SP_.eminx <= :5 AND SP_.eminy <= :6 AND SP_.emaxx >= :7 AND SP_.emaxy >= :8) S_, SDE.F1464
33:
SHAPE WHERE S_.sp_fid = SHAPE.fid
34:
END OF STMT
35:
EXEC #45:c=1000,e=822,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1262005426089006
36: WAIT #45: nam='SQL*Net message to client' ela= 3 driver id=1413697536 #bytes=1 p3=0 obj#=92612 tim=1262005426095016
37: WAIT #45: nam='SQL*Net more data to client' ela= 39 driver id=1413697536 #bytes=2004 p3=0 obj#=92612 tim=1262005426095401
38: WAIT #45: nam='SQL*Net more data to client' ela= 23 driver id=1413697536 #bytes=2000 p3=0 obj#=92612 tim=1262005426096039
39:
FETCH #45:c=10998,e=10823,p=0,cr=50,cu=0,mis=0,r=57,dep=0,og=1,tim=1262005426099931
红色部分为前端软件所提交的SQL,第二个SQL即为S和F表联合查询的语句。同时请注意绿色部分的内容,dep=0 代表该SQL是应用软件所提交的SQL,并不是oracle自己内部所执行的SQL,uid=68代表执行该SQL语句的用户ID为SDE,见下面的数据:
1: SQL > select user_id from dba_users where username='SDE' ;
2:
3:
USER_ID
4: ----------
5:
68
至于如何抓取Oracle后台的日志,以及日志中的各项内容都代表什么意思,可以查看以下的链接:
http://blog.csdn.net/liufeng1980423/archive/2010/12/13/6072515.aspx
http://blog.csdn.net/liufeng1980423/archive/2010/12/14/6074521.aspx