2012년 1월 31일 화요일

[PostGIS]ERROR: LWGEOM_estimated_extent

GeoServer 등 GeoTools를 사용하는 프로그램의 경우 PostGIS Data Store를 사용하여 레이어의Extent를 구할 때 다음과 같은 오류가 발생하는 경우가 있다.

▣ GeoTools - PostGIS
Map<String, Serializable> params = new HashMap<String, Serializable>();
params.put(JDBCDataStoreFactory.DBTYPE.key, "postgis");
params.put(JDBCDataStoreFactory.HOST.key, "localhost");
params.put(JDBCDataStoreFactory.PORT.key, 5432);
params.put(JDBCDataStoreFactory.SCHEMA.key, "public");
params.put(JDBCDataStoreFactory.DATABASE.key, "uoc");
params.put(JDBCDataStoreFactory.USER.key, "postgres");
params.put(JDBCDataStoreFactory.PASSWD.key, "postgis");

try {
    DataStore pgDataStore = DataStoreFinder.getDataStore(params);

    SimpleFeatureSource srcSfs = pgDataStore.getFeatureSource("ubsm0103");
    ReferencedEnvelope extent = srcSfs.getFeatures(Filter.INCLUDE).getBounds();

    System.out.println(extent);
} catch (IOException e) {
    LOGGER.log(Level.FINE, e.getMessage(), e);
}
▣ 오류
Warning: Failed to use ST_Estimated_Extent, falling back on envelope aggregation
org.postgresql.util.PSQLException: ERROR: LWGEOM_estimated_extent: couldn't locate table within current schema
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2062)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1795)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:479)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:353)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:252)
    at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208)
    at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208)
    at org.geotools.data.postgis.PostGISDialect.getOptimizedBounds(PostGISDialect.java:230)
    at org.geotools.jdbc.JDBCDataStore.getBounds(JDBCDataStore.java:1092)
    at org.geotools.jdbc.JDBCFeatureSource.getBoundsInternal(JDBCFeatureSource.java:478)
    at org.geotools.jdbc.JDBCFeatureStore.getBoundsInternal(JDBCFeatureStore.java:179)
    at org.geotools.data.store.ContentFeatureSource.getBounds(ContentFeatureSource.java:370)
    at org.geotools.data.store.ContentFeatureCollection.getBounds(ContentFeatureCollection.java:274)
▣ 오류원인
PostGISDialect.java 소스의 getOptimizedBounds 메쏘드를 찾아보면 다음과 같은 SQL문을 확인할 수 있다.
select AsText(force_2d(Envelope(ST_Estimated_Extent('ubsm0103', 'the_geom'))))
또는
SELECT ST_AsText(ST_Force_2D(ST_Envelope(ST_Estimated_Extent('ubsm0103', 'the_geom'))))
위 SQL에서 ST_Estimated_Extent 함수는 PostgreSQL 8.0.0 버전 이상에서는 VACUUM ANALYZE, PostgreSQL 8.0.0 이전 버전에서는 update_geometry_stats() 을 먼저 수행 해야 한다.

ST_Extent 함수를 사용하지 않은 이유는 속도때문입니다.

▣ 해결
PostGIS 초기 데이터 로딩 후 다음을 수행한다.
VACUUM ANALYZE
▣ 참고

 - http://docs.geotools.org/stable/javadocs/org/geotools/data/postgis/PostGISDialect.html
 - http://www.postgis.org/docs/ST_Estimated_Extent.html
 - http://www.postgresql.org/docs/9.0/interactive/sql-vacuum.html