一、環境
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;