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