SDE表空间过大分析(STATES,STATE_LINEAGES表过大)
一、环境
ArcGIS10.1 Oracle11G
二、问题描述
在进行数据库巡检时候,发现SDE表空间占用较大(超过40GB),因我们使用的时候SDE表空间没有存储任何用户数据,只有SDE系统表,数据量这么大有些不正常。
三、问题分析
1、检查空间占用情况
SELECT * FROM (SELECT SEGMENT_NAME, SEGMENT_TYPE, ROUND (SUM(BYTES) / 1024 / 1024 ,0) SEGMENT_SIZE FROM (SELECT T.TABLESPACE_NAME, T.SEGMENT_NAME, T.SEGMENT_TYPE, T.BYTES FROM USER_SEGMENTS T WHERE 1 = 1 AND T.SEGMENT_TYPE NOT IN ('INDEX', 'LOBINDEX', 'LOBSEGMENT') UNION ALL SELECT T.TABLESPACE_NAME, UL.TABLE_NAME AS SEGMENT_NAME, 'TABLE' AS SEGMENT_TYPE, T.BYTES FROM USER_SEGMENTS T INNER JOIN USER_LOBS UL ON T.SEGMENT_NAME = UL.SEGMENT_NAME WHERE 1 = 1 AND T.SEGMENT_TYPE = 'LOBSEGMENT' UNION ALL SELECT T.TABLESPACE_NAME, UI.TABLE_NAME AS SEGMENT_NAME, 'TABLE' AS SEGMENT_TYPE, T.BYTES FROM USER_SEGMENTS T INNER JOIN USER_INDEXES UI ON T.SEGMENT_NAME = UI.INDEX_NAME WHERE 1 = 1 AND T.SEGMENT_TYPE IN ('INDEX', 'LOBINDEX') AND 1 = 1) T WHERE 1 = 1 GROUP BY SEGMENT_NAME, SEGMENT_TYPE) T WHERE 1 = 1 ORDER BY SEGMENT_SIZE DESC;
可以看到占用较大的是STATE_LINEAGES表,采用SQL语句查看其数据条数,发现数据量到达8亿多条,这明显是不正常的。
注意:当时还发现部分索引占用空间较大,对索引进行重建即可。
select t.TABLE_NAME,t.NUM_ROWS from user_tables t where t.NUM_ROWS is not null order by t.NUM_ROWS desc;
2、对STATE_LINEAGES表进行分析
经过查阅相关资料,STATE_LINEAGES表和STATES表主要是负责记录版本编辑的信息(对于版本编辑不熟悉的可以参见一下ArcGIS官方文档,其主要是注册版本后可以多人同时在线编辑)。
版本编辑参考:
ArcSDE的版本管理机制_51CTO博客_arcgis版本管理
ArcGIS Help 10.1 - Versioned tables in a geodatabase in SQL Server
但是我们这边没有用到版本,我的库里面也没有注册任何版本,为了避免遗漏,咨询公司DBA通过SQL进行查询:
select owner,table_name from table_registry where bitand(object_flags,power(2,3))>0;
查询结果后发现,只有个别图层注册了版本,经过检查,这几个图层所在的表空间已经删除,此些记录也只是遗留下来的脏数据而已,这样可以确定没有注册版本的图层。
3、对STATE_LINEAGES表内数据进行分析
select t.owner,count(*) from states t group by t.owner order by count(*) desc;
发现记录均集中在特定的几个用户之中,根据业务分析,这几个用户都是涉及到数据上图的用户;
说明:我们这里对数据的处理都是通过SOE扩展地图服务功能实现数据增删改的,一般只是涉及增加和删除操作。
4、系统以及表清空测试(测试环境)
根据DBA描述,如果没有用到版本编辑,相应的表是可以清空的,我这里进行相关测试
A、通过系统上图功能测试,每次点击保存界址点的时候是会对数据进行删除后再新增(逻辑明显有问题,应该只有界址点发生改变时才触发此操作,测试),在STATE_LINEAGES表中会新增记录;
B、清空STATE_LINEAGES表(注意表有相关联的索引、主键等,为了不破坏相应的关系,建议原表备份删除后进行重建)
我这里因测试环境数据量比较小(注意,这仅仅适用于数据量不大的情况),采用下面语句进行表备份清空:
CREATE TABLE STATES_1 AS SELECT * FROM STATES; CREATE TABLE STATE_LINEAGES_1 AS SELECT * FROM STATE_LINEAGES;
DELETE FROM STATES; DELETE FROM STATE_LINEAGES;
如果要恢复数据,只要通过之前备份的语句重建表之后,将记录插回去即可。
INSERT INTO STATES SELECT * FROM STATES_1; INSERT INTO STATE_LINEAGES SELECT * FROM STATE_LINEAGES_1;
在系统中点击保存时候会报错,通过跟踪ArcGIS Server日志,错误信息如下:
【DeleteData】:删除失败.错误消息:Underlying DBMS error [Error executing stored procedure sde.version_util.insert_state::ORA-06508: PL/SQL: 无法找到正在调用 的程序单元] [SDE.DEFAULT][STATE_ID = 15677]
5、SOE检查,原因明确
通过上免的测试可以发现,基本就是通过SOE进行数据删除的方法有问题了,让开发检查相关语句,是否有版本编辑相关的内容,结果发现在做编辑的时候使用了以下语句:
muWorkspaceEdit.StartMultiuserEditing(esriMultiuserEditSessionMode.esriMESMVersioned);
这明显是使用了基于版本的方法,修改成下面的方法并重新编译SOE
muWorkspaceEdit.StartMultiuserEditing(esriMultiuserEditSessionMode.esriMESMNonVersioned);
四、问题解决与后续跟踪
SOE修改编译后,将现场地图服务所使用的SOE进行全部替换(如果有多个站点使用了此SOE,不要有遗漏);
在后续跟踪STATE_LINEAGES表中数据产生情况
select to_char(t.creation_time,'yyyymmdd'),count(*) from STATES t group by to_char(t.creation_time,'yyyymmdd') order by to_char(t.creation_time,'yyyymmdd') desc;
select to_char(t.creation_time,'yyyymmdd'),t.owner,count(*) from STATES t group by t.owner,to_char(t.creation_time,'yyyymmdd') order by to_char(t.creation_time,'yyyymmdd') desc;
经过跟踪测试,后续的上图以及数据删除等不会再在STATE_LINEAGES表中差生新的记录。
在测试环境下清空STATE_LINEAGES表之后,删除以及上图也不会再有错误,同步使用ArcGIS进行数据编辑、版本注册等操作,验证也没有任何问题,数据表增长的情况得以解决!
至于现在已有的存量数据,可以考虑备份后情况或者记录保留均可以,只要后续不再增长,问题不大!
最后附上两个表的建表语句
-- Create table create table STATE_LINEAGES ( lineage_name INTEGER not null, lineage_id INTEGER not null ) tablespace SDE_TBS pctfree 5 initrans 4 maxtrans 255 storage ( initial 7M next 1M minextents 1 maxextents unlimited ); -- Create/Recreate indexes create index LINEAGE_ID_IDX2 on STATE_LINEAGES (LINEAGE_ID) tablespace SDE_TBS pctfree 5 initrans 4 maxtrans 255 storage ( initial 10M next 4M minextents 1 maxextents unlimited ); -- Create/Recreate primary, unique and foreign key constraints alter table STATE_LINEAGES add constraint LINEAGES_PK primary key (LINEAGE_NAME, LINEAGE_ID) using index tablespace SDE_TBS pctfree 10 initrans 2 maxtrans 255 storage ( initial 64K next 1M minextents 1 maxextents unlimited ); -- Grant/Revoke object privileges grant select on STATE_LINEAGES to PUBLIC; -- STATES表的相关语句 -- Create table create table STATES ( state_id INTEGER not null, owner NVARCHAR2(32) not null, creation_time DATE not null, closing_time DATE, parent_state_id INTEGER not null, lineage_name INTEGER not null ) tablespace SDE_TBS pctfree 10 initrans 4 maxtrans 255 storage ( initial 1M next 128K minextents 1 maxextents unlimited ); -- Create/Recreate primary, unique and foreign key constraints alter table STATES add constraint STATES_PK primary key (STATE_ID) using index tablespace SDE_TBS pctfree 10 initrans 5 maxtrans 255 storage ( initial 320K next 128K minextents 1 maxextents unlimited ); alter table STATES add constraint STATES_CUK unique (PARENT_STATE_ID, LINEAGE_NAME) using index tablespace SDE_TBS pctfree 10 initrans 5 maxtrans 255 storage ( initial 384K next 128K minextents 1 maxextents unlimited ); -- Grant/Revoke object privileges grant select on STATES to PUBLIC;
posted on 2025-10-23 15:10 jingkunliu 阅读(6) 评论(0) 收藏 举报