# Chapter 4. Data Management

## 4.1. GIS (벡터) 데이터 로드

### 4.1.1. OGC Geometry

The Open Geospatial Consortium (OGC) developed the Simple Features Access standard (SFA) to provide a model for geospatial data. It defines the fundamental spatial type of Geometry, along with operations which manipulate and transform geometry values to perform spatial analysis tasks. PostGIS implements the OGC Geometry model as the PostgreSQL data types geometry and geography.

Geometry is an abstract type. Geometry values belong to one of its concrete subtypes which represent various kinds and dimensions of geometric shapes. These include the atomic types Point, LineString, LinearRing and Polygon, and the collection types MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. The Simple Features Access - Part 1: Common architecture v1.2.1 adds subtypes for the structures PolyhedralSurface, Triangle and TIN.

Geometry models shapes in the 2-dimensional Cartesian plane. The PolyhedralSurface, Triangle, and TIN types can also represent shapes in 3-dimensional space. The size and location of shapes are specified by their coordinates. Each coordinate has a X and Y ordinate value determining its location in the plane. Shapes are constructed from points or line segments, with points specified by a single coordinate, and line segments by two coordinates.

Coordinates may contain optional Z and M ordinate values. The Z ordinate is often used to represent elevation. The M ordinate contains a measure value, which may represent time or distance. If Z or M values are present in a geometry value, they must be defined for each point in the geometry. If a geometry has Z or M ordinates the coordinate dimension is 3D; if it has both Z and M the coordinate dimension is 4D.

Geometry values are associated with a spatial reference system indicating the coordinate system in which it is embedded. The spatial reference system is identified by the geometry SRID number. The units of the X and Y axes are determined by the spatial reference system. In planar reference systems the X and Y coordinates typically represent easting and northing, while in geodetic systems they represent longitude and latitude. SRID 0 represents an infinite Cartesian plane with no units assigned to its axes. See Section 4.5, “SPATIAL_REF_SYS 테이블과 공간 참조 시스템”.

The geometry dimension is a property of geometry types. Point types have dimension 0, linear types have dimension 1, and polygonal types have dimension 2. Collections have the dimension of the maximum element dimension.

A geometry value may be empty. Empty values contain no vertices (for atomic geometry types) or no elements (for collections).

An important property of geometry values is their spatial extent or bounding box, which the OGC model calls envelope. This is the 2 or 3-dimensional box which encloses the coordinates of a geometry. It is an efficient way to represent a geometry's extent in coordinate space and to check whether two geometries interact.

The geometry model allows evaluating topological spatial relationships as described in Section 5.1.1, “Dimensionally Extended 9-Intersection Model”. To support this the concepts of interior, boundary and exterior are defined for each geometry type. Geometries are topologically closed, so they always contain their boundary. The boundary is a geometry of dimension one less than that of the geometry itself.

The OGC geometry model defines validity rules for each geometry type. These rules ensure that geometry values represents realistic situations (e.g. it is possible to specify a polygon with a hole lying outside the shell, but this makes no sense geometrically and is thus invalid). PostGIS also allows storing and manipulating invalid geometry values. This allows detecting and fixing them if needed. See Section 4.4, “Geometry Validation”

#### 4.1.1.1. Point

A Point is a 0-dimensional geometry that represents a single location in coordinate space.

```POINT (1 2)
POINT Z (1 2 3)
POINT ZM (1 2 3 4)
```

#### 4.1.1.2. LineString

A LineString is a 1-dimensional line formed by a contiguous sequence of line segments. Each line segment is defined by two points, with the end point of one segment forming the start point of the next segment. An OGC-valid LineString has either zero or two or more points, but PostGIS also allows single-point LineStrings. LineStrings may cross themselves (self-intersect). A LineString is closed if the start and end points are the same. A LineString is simple if it does not self-intersect.

`LINESTRING (1 2, 3 4, 5 6)`

#### 4.1.1.3. LinearRing

A LinearRing is a LineString which is both closed and simple. The first and last points must be equal, and the line must not self-intersect.

`LINEARRING (0 0 0, 4 0 0, 4 4 0, 0 4 0, 0 0 0)`

#### 4.1.1.4. Polygon

A Polygon is a 2-dimensional planar region, delimited by an exterior boundary (the shell) and zero or more interior boundaries (holes). Each boundary is a LinearRing.

`POLYGON ((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))`

#### 4.1.1.5. MultiPoint

A MultiPoint is a collection of Points.

`MULTIPOINT ( (0 0), (1 2) )`

#### 4.1.1.6. MultiLineString

A MultiLineString is a collection of LineStrings. A MultiLineString is closed if each of its elements is closed.

`MULTILINESTRING ( (0 0,1 1,1 2), (2 3,3 2,5 4) )`

#### 4.1.1.7. MultiPolygon

A MultiPolygon is a collection of non-overlapping, non-adjacent Polygons. Polygons in the collection may touch only at a finite number of points.

`MULTIPOLYGON (((1 5, 5 5, 5 1, 1 1, 1 5)), ((6 5, 9 1, 6 1, 6 5)))`

#### 4.1.1.8. GeometryCollection

A GeometryCollection is a heterogeneous (mixed) collection of geometries.

`GEOMETRYCOLLECTION ( POINT(2 3), LINESTRING(2 3, 3 4))`

#### 4.1.1.9. PolyhedralSurface

A PolyhedralSurface is a contiguous collection of patches or facets which share some edges. Each patch is a planar Polygon. If the Polygon coordinates have Z ordinates then the surface is 3-dimensional.

```POLYHEDRALSURFACE Z (
((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)),
((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)),
((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)),
((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )```

#### 4.1.1.10. Triangle

A Triangle is a polygon defined by three distinct non-collinear vertices. Because a Triangle is a polygon it is specified by four coordinates, with the first and fourth being equal.

`TRIANGLE ((0 0, 0 9, 9 0, 0 0))`

#### 4.1.1.11. TIN

A TIN is a collection of non-overlapping Triangles representing a Triangulated Irregular Network.

`TIN Z ( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )`

### 4.1.2. SQL-MM Part 3

The ISO/IEC 13249-3 SQL Multimedia - Spatial standard (SQL/MM) extends the OGC SFA to define Geometry subtypes containing curves with circular arcs. The SQL/MM types support 3DM, 3DZ and 4D coordinates.

 SQL-MM 실행 과정에서 지정된 허용 오차를 기준으로 부동소수점을 비교합니다. 현재 허용 오차는 1E-8입니다.

#### 4.1.2.1. CircularString

CIRCULARSTRING은 기본 곡선 유형으로, 선형계의 LINESTRING과 비슷합니다. 단일 분절에는 시작점과 종단점(첫 번째 및 세 번째) 그리고 곡선 위의 다른 한 점 이렇게 포인트 세 개가 필요합니다. 예외는 닫힌 원으로, 이 경우 시작점과 종단점이 동일합니다. 이 경우 두 번째 포인트는 원호의 중심, 즉 원의 반대편이 되어야만 합니다. 원호를 함께 묶으려면, LINESTRING과 마찬가지로 한 원호의 마지막 포인트가 다음 원호의 첫 번째 포인트가 되어야 합니다. 즉 유효한 원형 스트링은 1을 초과하는 홀수 개수의 포인트들을 가져야만 한다는 뜻입니다.

```CIRCULARSTRING(0 0, 1 1, 1 0)

CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0)```

#### 4.1.2.2. CompoundCurve

복심곡선(compound curve)이란 곡선(원호) 분절과 선형 분절이 함께 있는 연속적인 단일 곡선을 말합니다. 즉 구성 요소들이 잘 형성되어야 함은 물론, (마지막을 제외한) 모든 구성 요소의 종단점이 다음 구성 요소의 시작점과 일치해야한 한다는 뜻입니다.

`COMPOUNDCURVE( CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))`

#### 4.1.2.3. CurvePolygon

CURVEPOLYGON은 일반 폴리곤입니다. 외곽선과 함께 0개 이상의 내곽선을 가지고 있을 뿐입니다. 차이라면 내외곽선이 원형 스트링, 선형 스트링, 또는 복합 스트링 형태를 할 수 있다는 점입니다.

PostGIS는 1.4버전부터 만곡 폴리곤에 대해 복심곡선을 지원합니다.

```CURVEPOLYGON(
CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),
(1 1, 3 3, 3 1, 1 1) )```

Example: A CurvePolygon with the shell defined by a CompoundCurve containing a CircularString and a LineString, and a hole defined by a CircularString

```CURVEPOLYGON(
COMPOUNDCURVE( CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),
(4 3, 4 5, 1 4, 0 0)),
CIRCULARSTRING(1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1) )```

#### 4.1.2.4. MultiCurve

MULTICURVE는 원형 스트링, 선형 스트링, 복합 스트링을 포함할 수 있는 곡선 집합입니다.

`MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4))`

#### 4.1.2.5. MultiSurface

MULTISURFACE는 면 집합으로, (선형) 폴리곤일 수도 만곡 폴리곤일 수도 있습니다.

```MULTISURFACE(
CURVEPOLYGON(
CIRCULARSTRING( 0 0, 4 0, 4 4, 0 4, 0 0),
(1 1, 3 3, 3 1, 1 1)),
((10 10, 14 12, 11 10, 10 10), (11 11, 11.5 11, 11 11.5, 11 11)))```

### 4.1.3. OpenGIS WKB 및 WKT

OpenGIS사양서에는 공간 오브젝트들을 나타내는 두 가지 표준 방법이 정의되어 있습니다: Well-Known Text (WKT) 형태와 Well-Known Binary (WKB) 형태. WKT와 WKB 모두 오브젝트 타입과 오브젝트를 구성하는 좌표들에 대한 정보를 포함하고 있습니다.

공간 참조 시스템의 WKT(Well-Known Text) 표현식입니다. 다음은 WKT SRS 표현식의 예입니다:

• POINT(0 0)

• POINT(0 0)

• POINT(0 0)

• POINT EMPTY

• LINESTRING(0 0,1 1,1 2)

• LINESTRING

• POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))

• MULTIPOINT((0 0),(1 2))

• MULTIPOINT((0 0),(1 2))

• MULTIPOINT

• MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))

• MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))

• GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))

• GEOMETRYCOLLECTION

Input and output of WKT is provided by the functions ST_AsText and ST_GeomFromText:

```text WKT = ST_AsText(geometry);
geometry = ST_GeomFromText(text WKT, SRID);```

예를 들어 OGC 공간 객체를 생성하고 삽입하기 위한 유효한 삽입 구문은 다음과 같을 것입니다:

```INSERT INTO geotable ( geom, name )
VALUES ( ST_GeomFromText('POINT(-126.4 45.32)', 312), 'A Place');```

Well-Known Binary (WKB) provides a portable, full-precision representation of spatial data as binary data (arrays of bytes). Examples of the WKB representations of spatial objects are:

• POINT(0 0)

WKB: 0101000000000000000000F03F000000000000F03

• LINESTRING(0 0,1 1,1 2)

WKB: 0102000000020000000000000000000040000000000000004000000000000022400000000000002240

Input and output of WKB is provided by the functions ST_AsBinary and ST_GeomFromWKB:

```bytea WKB = ST_AsBinary(geometry);
geometry = ST_GeomFromWKB(bytea WKB, SRID);
```

예를 들어 OGC 공간 객체를 생성하고 삽입하기 위한 유효한 삽입 구문은 다음과 같을 것입니다:

```INSERT INTO geotable ( geom, name )
VALUES ( ST_GeomFromWKB('\x0101000000000000000000f03f000000000000f03f', 312), 'A Place');```

## 4.2. Geometry Data Type

PostGIS implements the OGC Simple Features model by defining a PostgreSQL data type called `geometry`. It represents all of the geometry subtypes by using an internal type code (see GeometryType and ST_GeometryType). This allows modelling spatial features as rows of tables defined with a column of type `geometry`.

The `geometry` data type is opaque, which means that all access is done via invoking functions on geometry values. Functions allow creating geometry objects, accessing or updating all internal fields, and compute new geometry values. PostGIS supports all the functions specified in the OGC Simple feature access - Part 2: SQL option (SFS) specification, as well many others. See Chapter 7, PostGIS Reference for the full list of functions.

 PostGIS follows the SFA standard by prefixing spatial functions with "ST_". This was intended to stand for "Spatial and Temporal", but the temporal part of the standard was never developed. Instead it can be interpreted as "Spatial Type".

OpenGIS 사양서는 공간 객체의 내부 저장 형식이 공간 참조 시스템 식별자(SRID)를 포함하도록 요구합니다. 데이터베이스에 삽입될 공간 객체 생성시 SRID가 필요합니다.

To make querying geometry efficient PostGIS defines various kinds of spatial indexes, and spatial operators to use them. See Section 4.9, “인덱스 빌드 작업” and Section 5.2, “Using Spatial Indexes” for details.

### 4.2.1. OpenGIS WKB 및 WKT

OGC SFA specifications initially supported only 2D geometries, and the geometry SRID is not included in the input/output representations. The OGC SFA specification 1.2.1 (which aligns with the ISO 19125 standard) adds support for 3D (ZYZ) and measured (XYM and XYZM) coordinates, but still does not include the SRID value.

Because of these limitations PostGIS defined extended EWKB and EWKT formats. They provide 3D (XYZ and XYM) and 4D (XYZM) coordinate support and include SRID information. Including all geometry information allows PostGIS to use EWKB as the format of record (e.g. in DUMP files).

EWKB and EWKT are used for the "canonical forms" of PostGIS data objects. For input, the canonical form for binary data is EWKB, and for text data either EWKB or EWKT is accepted. This allows geometry values to be created by casting a text value in either HEXEWKB or EWKT to a geometry value using `::geometry`. For output, the canonical form for binary is EWKB, and for text it is HEXEWKB (hex-encoded EWKB).

For example this statement creates a geometry by casting from an EWKT text value, and outputs it using the canonical form of HEXEWKB:

```SELECT 'SRID=4;POINT(0 0)'::geometry;
geometry
----------------------------------------------------
01010000200400000000000000000000000000000000000000
```

PostGIS EWKT output has a few differences to OGC WKT:

• For 3DZ geometries the Z qualifier is omitted:

POINT(0 0)

POINT(0 0)

• For 3DM geometries the M qualifier is included:

POINT(0 0)

POINT(0 0)

• For 4D geometries the ZM qualifier is omitted:

POINT(0 0)

POINT(0 0)

EWKT avoids over-specifying dimensionality and the inconsistencies that can occur with the OGC/ISO format, such as:

• POINT(0 0)

• POINT(0 0)

• POINT(0 0)

 PostGIS는 현재 OGC 형식의 상위 집합인 형식을 확장합니다(유효한 모든 WKB/WKT는 유효한 EWKB/EWKT가 됩니다). 하지만 향후 달라질 수도 있습니다. 특히 OGC가 PostGIS 확장 프로그램과 상충하는 새 형식을 들고 나온다면 말입니다. 그러므로 이 피처에 의존해서는 안 됩니다!

피쳐들의 공간 오브젝트들의 텍스트 문자열표현들(WKT) 의 예들로는 다음과 같은 것들이 있습니다:

• POINT(0 0 0) -- XYZ

• SRID=32632;POINT(0 0) -- SRID 추가 XY

• POINTM(0 0 0) -- XYM

• POINT(0 0 0 0) -- XYZM

• SRID=4326;MULTIPOINTM(0 0 0,1 2 1) -- SRID 추가 XYM

• MULTILINESTRING((0 0 0,1 1 0,1 2 1),(2 3 1,3 2 1,5 4 1))

• POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))

• MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)),((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0)))

• GEOMETRYCOLLECTIONM( POINTM(2 3 9), LINESTRINGM(2 3 4, 3 4 5) )

• MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4) )

• POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )

• TRIANGLE ((0 0, 0 9, 9 0, 0 0))

• TIN( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )

다음과 같은 인터페이스를 이용해서 이 형식을 입력/출력할 수 있습니다.

```bytea EWKB = ST_AsEWKB(geometry);
text EWKT = ST_AsEWKT(geometry);
geometry = ST_GeomFromEWKB(bytea EWKB);
geometry = ST_GeomFromEWKT(text EWKT);```

예를 들어 PostGIS 공간 객체를 생성하고 삽입하기 위한 유효한 삽입 구문은 다음과 같을 것입니다:

```INSERT INTO geotable ( geom, name )
VALUES ( ST_GeomFromEWKT('SRID=312;POINTM(-126.4 45.32 15)'), 'A Place' )```

## 4.3. PostGIS 지리형 유형

지리형 유형은 (종종 "측지" 좌표, 또는 "위도/경도"나 "경도/위도"라고 불리는) "지리" 좌표로 표현되는 공간 피처를 자체적으로 지원합니다. 지리 좌표는 각도 단위(도)를 사용하는 구면(球面) 좌표입니다.

PostGIS 도형 유형은 평면을 기반으로 합니다. 평면상에서 두 포인트 사이의 가장 짧은 경로는 직선입니다. 즉 데카르트 수학과 직선 벡터를 이용해서 도형에 대해 계산(면적, 거리, 길이, 교차점 등)한다는 뜻입니다.

PostGIS 지리형 유형은 구면을 기반으로 합니다. 구면상에서 두 포인트 사이의 가장 짧은 경로는 대권(大圈; great circle arc)입니다. 즉 지리형에 대한 계산(면적, 거리, 길이, 교차점 등)은 더 복잡한 수학을 이용해서 구면상에서 이루어져야 한다는 뜻입니다. 더 정확하게 측정하려면 지구의 실제 회전타원체(spheroidal shape)를 고려해서 계산해야 하는데, 수학이 아주 복잡해질 수밖에 없습니다.

기저 수학이 훨씬 더 복잡하기 때문에, 지리형 유형을 위해 정의된 함수는 도형 유형의 함수보다 더 적습니다. 시간이 지날수록 새 알고리즘이 추가되어 지리형 유형의 역량은 확장될 것입니다.

Like the geometry data type, geography data is associated with a spatial reference system via a spatial reference system identifier (SRID). Any geodetic (long/lat based) spatial reference system defined in the `spatial_ref_sys` table can be used. (Prior to PostGIS 2.2, the geography type supported only WGS 84 geodetic (SRID:4326)). You can add your own custom geodetic spatial reference system as described in Section 4.5.2, “SPATIAL_REF_SYS 테이블과 공간 참조 시스템”.

For all spatial reference systems the units returned by measurement functions (e.g. ST_Distance, ST_Length, ST_Perimeter, ST_Area) and for the distance argument of ST_DWithin are in meters.

### 4.3.1. 공간 테이블 생성

You can create a table to store geography data using the CREATE TABLE SQL statement with a column of type `geography`. The following example creates a table with a geography column storing 2D LineStrings in the WGS84 geodetic coordinate system (SRID 4326):

```CREATE TABLE global_points (
id SERIAL PRIMARY KEY,
name VARCHAR(64),
location geography(POINT,4326)
);```

The geography type supports two optional type modifiers:

• 유형 변경자가 허용하는 값은 다음과 같습니다. POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON. 또 이 변경자는 Z, M 및 ZM이라는 접미사를 통해 차원수 제약도 지원합니다. 따라서, 예를 들자면 'LINESTRINGM'의 변경자는 3차원 이하의 라인 스트링만을 허용할 것이며, 세 번째 차원을 기준으로 취급할 것입니다. 마찬가지로 'POINTZM'은 네 가지 차원의 데이터를 입력해야 할 것입니다.

• the SRID modifier restricts the spatial reference system SRID to a particular number. If omitted, the SRID defaults to 4326 (WGS84 geodetic), and all calculations are performed using WGS84.

Examples of creating tables with geography columns:

• POINT: 2D 포인트 도형을 담은 테이블 생성:

`CREATE TABLE ptgeogwgs(gid serial PRIMARY KEY, geog geography(POINT) );`
• POINT: 2D 포인트 도형을 담은 테이블 생성:

`CREATE TABLE ptgeognad83(gid serial PRIMARY KEY, geog geography(POINT,4269) );`
• Create a table with 3D (XYZ) POINTs and an explicit SRID of 4326:

`CREATE TABLE ptzgeogwgs84(gid serial PRIMARY KEY, geog geography(POINTZ,4326) );`
• Create a table with 2D LINESTRING geography with the default SRID 4326:

`CREATE TABLE lgeog(gid serial PRIMARY KEY, geog geography(LINESTRING) );`
• POINT: 2D 포인트 도형을 담은 테이블 생성:

`CREATE TABLE lgeognad27(gid serial PRIMARY KEY, geog geography(POLYGON,4267) );`

Geography fields are registered in the `geography_columns` system view. You can query the `geography_columns` view and see that the table is listed:

`SELECT * FROM geography_columns;`

도형과 동일한 방법으로 인덱스를 생성합니다. PostGIS가 열 유형이 지리형인 것을 감지하고 일반적인 도형 용 평면 인덱스 대신 적절한 구면 기반 인덱스를 생성할 것입니다.

```-- Index the test table with a spherical index
CREATE INDEX global_points_gix ON global_points USING GIST ( location );```

### 4.3.2. PostGIS 지리형 유형

You can insert data into geography tables in the same way as geometry. Geometry data will autocast to the geography type if it has SRID 4326. The EWKT and EWKB formats can also be used to specify geography values.

```-- Add some data into the test table
INSERT INTO global_points (name, location) VALUES ('Town', 'SRID=4326;POINT(-110 30)');
INSERT INTO global_points (name, location) VALUES ('Forest', 'SRID=4326;POINT(-109 29)');
INSERT INTO global_points (name, location) VALUES ('London', 'SRID=4326;POINT(0 49)');
```

Any geodetic (long/lat) spatial reference system listed in `spatial_ref_sys` table may be specified as a geography SRID. Non-geodetic coordinate systems raise an error if used.

```-- NAD 83 lon/lat
SELECT 'SRID=4269;POINT(-123 34)'::geography;
geography
----------------------------------------------------
```
```-- NAD27 lon/lat
SELECT 'SRID=4267;POINT(-123 34)'::geography;
geography
----------------------------------------------------
0101000020AB1000000000000000C05EC00000000000004140
```
```-- NAD83 UTM zone meters - gives an error since it is a meter-based planar projection
SELECT 'SRID=26910;POINT(-123 34)'::geography;

ERROR:  Only lon/lat coordinate systems are supported in geography.
```

쿼리 및 측정 함수는 미터 단위를 사용합니다. 따라서 거리 파라미터는 미터로 표현되어야 하고, 반환값도 미터(또는 면적의 경우 평방미터) 단위가 될 것입니다.

```-- A distance query using a 1000km tolerance
SELECT name FROM global_points WHERE ST_DWithin(location, 'SRID=4326;POINT(-110 29)'::geography, 1000000);```

시애틀에서 런던으로 가는 비행기가(LINESTRING(-122.33 47.606, 0.0 51.5)) 레이캬비크에(POINT(-21.96 64.15)) 얼마나 접근하는지 계산해보면, 실제 계산시 지리형이 얼마나 강력한지 알 수 있습니다.

지리형 유형이 시애틀과 런던을 잇는 대권항로와 레이캬비크 사이의 구면 상 가장 짧은 거리를 실제로 계산할 수 있습니다.

```-- Distance calculation using GEOGRAPHY
SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geography, 'POINT(-21.96 64.15)'::geography);
st_distance
-----------------
122235.23815667```

대권 매퍼(Great Circle mapper) 도형 유형은 평면 세계지도 상에서 시애틀과 런던을 직선으로 잇는 경로와 레이캬비크 사이의 아무 의미도 없는 데카르트 거리를 계산합니다. 결과값의 명목상 단위를 "도(degree)"라고 할 수도 있겠지만, 결과값은 세 포인트 사이의 어떤 실제 각도 차이도 반영하지 않기 때문에 "도"라고 하는 것조차 부정확한 일이 됩니다.

```-- Distance calculation using GEOMETRY
SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geometry, 'POINT(-21.96 64.15)'::geometry);
st_distance
--------------------
13.342271221453624
```

### 4.3.3. 도형 데이터 유형과 지리형 데이터 유형을 중첩해서 이용하는 경우

새로운 지리형 유형은 데이터를 경도/위도 좌표로 저장할 수 있도록 해주지만, 단점도 있습니다. 도형을 대상으로 정의된 함수보다 지리형 대상 함수가 더 적고, 그 정의된 함수도 실행하는 데 CPU 시간을 더 많이 잡아먹습니다.

사용자가 선택한 유형은 사용자가 빌드하는 응용 프로그램 영역에서 기대한대로 동작하도록 적합한 조건을 갖춰야 합니다. 사용자 데이터가 전세계 또는 광대한 대륙 지역을 포괄할 예정입니까 아니면 시, 도, 군 또는 그 이하의 지자체에 국한될 예정입니까?

• 사용자 데이터가 좁은 지역에 국한된다면, 사용 가능한 실행성 및 기능성 관점에서, 적합한 투영을 선택하고 도형을 이용하는 것이 최선의 해결책이 될 수도 있습니다.

• 사용자 데이터가 전세계 또는 대륙에 걸쳐 있을 경우, 지리형을 이용하면 일일이 어떤 투영법을 이용할지 고민하지 않고 시스템을 빌드할 수도 있습니다. 사용자 데이터를 경도/위도로 저장하고, 지리형을 대상으로 정의된 함수를 이용하십시오.

• 투영에 대한 이해가 부족하고, 따로 공부하고 싶지도 않으며, 지리형 사용시 기능성이 제한된다는 사실을 받아들일 준비가 되어 있다면, 도형보다 지리형을 사용하는 편이 더 쉬울 수 있습니다. 그냥 사용자 데이터를 경도/위도로 로드한 다음 작업을 시작하십시오.

지리형과 도형을 각각 지원하는 함수를 비교해보려면 Section 12.11, “PostGIS Function Support Matrix” 를 참조하십시오. 지리형 함수의 목록 및 설명을 간단하게 살펴보려면 Section 12.4, “PostGIS Geography Support Functions” 를 참조하십시오.

### 4.3.4. 지리형 고급 FAQ

 4.3.4.1. 계산 작업시 구체 상에서 계산하게 됩니까 회전타원체 상에서 하게 됩니까? 기본적으로, 모든 거리 및 면적 계산은 회전타원체 상에서 이루어집니다. 좁은 지역을 대상으로 한 계산의 결과와 해당 지역에 적절한 투영법을 적용한 평면 상 계산 결과는 일치할 것입니다. 더 넓은 지역이라면 투영법을 적용한 평면 상 계산보다 회전타원체 상 계산이 언제나 더 정확할 것입니다. 최종 불 파라미터 'FALSE'를 설정하면 모든 지리형 함수가 구체 상 계산을 할 수 있습니다. 이렇게 하면 계산 속도가 조금 빨라질 것입니다. 특히 도형들이 매우 단순한 경우에 말입니다. 4.3.4.2. 날짜변경선과 남극/북극은 어떻습니까? 모든 계산은 날짜변경선이나 양극을 고려하지 않고 이루어집니다. 좌표가 회전타원체(경도/위도)이기 때문에 날짜변경선을 지나는 형상이라도, 계산이라는 관점에서 보면, 다른 어떤 형상과도 다를 바가 없습니다. 4.3.4.3. 공간 처리할 수 있는 가장 긴 원호가 무엇인가요? 두 포인트 사이의 "보간 라인"으로 대권호(great circle arc)를 이용합니다. 즉 대권을 따라 어느 방향으로 이동하느냐에 따라 두 포인트가 실제로는 두 가지 방식으로 만난다는 뜻입니다. 모든 코드는 포인트들이 대권을 따라 가는 두 경로 가운데 '짧은' 경로로 만난다고 가정합니다. 결과적으로, 180도 이상의 원호를 가진다면 정확히 모델링된 형상이 아니게 됩니다. 4.3.4.4. 유럽이나 러시아의 면적을 계산하거나 또는 광대한 지역을 삽입하는 작업이 이렇게 느린 이유가 뭐지요? 폴리곤이 너무나 크기 때문이지요! 광대한 지역은 두 가지 이유로 좋지 않습니다. 먼저 경계가 워낙 길기 때문에 어떤 쿼리를 실행하든 인덱스가 피처 전체를 읽어오는 경향이 있습니다. 그리고 꼭짓점 개수도 너무 많아서 거리, 밀폐 여부 등의 테스트를 할 때 적어도 한 번, 때로는 n번 이상(이때 n은 다른 후보 피처의 꼭짓점 개수) 꼭짓점 목록 전체를 훑어야 하기 때문입니다. 도형의 경우, 대용량 폴리곤을 대상으로 좁은 지역에 대한 쿼리를 할 때 사용자 도형 데이터를 더 작은 덩어리들로 "비정규화"해서 인덱스가 효율적으로 객체의 일부분을 하위 쿼리(subquery)할 수 있도록 만들어 쿼리 시 매번 전체 객체를 읽어올 필요가 없도록 하는 편이 좋습니다. 유럽 전체를 폴리곤 한 개로 저장할 수 있다고 해서 꼭 그렇게 해야 한다는 뜻은 아닙니다.

## 4.4. Geometry Validation

PostGIS is compliant with the Open Geospatial Consortium’s (OGC) Simple Features specification. That standard defines the concepts of geometry being simple and valid. These definitions allow the Simple Features geometry model to represent spatial objects in a consistent and unambiguous way that supports efficient computation. (Note: the OGC SF and SQL/MM have the same definitions for simple and valid.)

### 4.4.1. Simple Geometry

A simple geometry is one that has no anomalous geometric points, such as self intersection or self tangency.

`POINT` 란 0차원 도형 객체로서 상속적으로 단순형 입니다.

`MULTIPOINT` 는 어떤 두 좌표(`POINT`)도 동일하지 않은 (동일한 좌표를 공유하지 않는) 단순형 입니다.

A `LINESTRING` is simple if it does not pass through the same point twice, except for the endpoints. If the endpoints of a simple LineString are identical it is called closed and referred to as a Linear Ring.

 (a) and (c) are simple `LINESTRING`s. (b) and (d) are not simple. (c) is a closed Linear Ring.
 (a) (b) (c) (d)

A `MULTILINESTRING` is simple only if all of its elements are simple and the only intersection between any two elements occurs at points that are on the boundaries of both elements.

 (e) and (f) are simple `MULTILINESTRING`s. (g) is not simple.
 (e) (f) (g)

`POLYGON`s are formed from linear rings, so valid polygonal geometry is always simple.

To test if a geometry is simple use the ST_IsSimple function:

```SELECT
ST_IsSimple('LINESTRING(0 0, 100 100)') AS straight,
ST_IsSimple('LINESTRING(0 0, 100 100, 100 0, 0 100)') AS crossing;

straight | crossing
----------+----------
t        | f
```

Generally, PostGIS functions do not require geometric arguments to be simple. Simplicity is primarily used as a basis for defining geometric validity. It is also a requirement for some kinds of spatial data models (for example, linear networks often disallow lines that cross). Multipoint and linear geometry can be made simple using ST_UnaryUnion.

### 4.4.2. Valid Geometry

Geometry validity primarily applies to 2-dimensional geometries (`POLYGON`s and `MULTIPOLYGON`s) . Validity is defined by rules that allow polygonal geometry to model planar areas unambiguously.

A `POLYGON` is valid if:

1. the polygon boundary rings (the exterior shell ring and interior hole rings) are simple (do not cross or self-touch). Because of this a polygon cannnot have cut lines, spikes or loops. This implies that polygon holes must be represented as interior rings, rather than by the exterior ring self-touching (a so-called "inverted hole").

2. boundary rings do not cross

3. boundary rings may touch at points but only as a tangent (i.e. not in a line)

4. interior rings are contained in the exterior ring

5. the polygon interior is simply connected (i.e. the rings must not touch in a way that splits the polygon into more than one part)

 (h) and (i) are valid `POLYGON`s. (j-m) are invalid. (j) can be represented as a valid `MULTIPOLYGON`.
 (h) (i) (j) (k) (l) (m)

A `MULTIPOLYGON` is valid if:

1. its element `POLYGON`s are valid

2. elements do not overlap (i.e. their interiors must not intersect)

3. elements touch only at points (i.e. not along a line)

 (n) is a valid `MULTIPOLYGON`. (o) and (p) are invalid.
 (n) (o) (p)

These rules mean that valid polygonal geometry is also simple.

For linear geometry the only validity rule is that `LINESTRING`s must have at least two points and have non-zero length (or equivalently, have at least two distinct points.) Note that non-simple (self-intersecting) lines are valid.

```SELECT
ST_IsValid('LINESTRING(0 0, 1 1)') AS len_nonzero,
ST_IsValid('LINESTRING(0 0, 0 0, 0 0)') AS len_zero,
ST_IsValid('LINESTRING(10 10, 150 150, 180 50, 20 130)') AS self_int;

len_nonzero | len_zero | self_int
-------------+----------+----------
t           | f        | t
```

`POINT` and `MULTIPOINT` geometries have no validity rules.

### 4.4.3. Managing Validity

PostGIS allows creating and storing both valid and invalid Geometry. This allows invalid geometry to be detected and flagged or fixed. There are also situations where the OGC validity rules are stricter than desired (examples of this are zero-length linestrings and polygons with inverted holes.)

Many of the functions provided by PostGIS rely on the assumption that geometry arguments are valid. For example, it does not make sense to calculate the area of a polygon that has a hole defined outside of the polygon, or to construct a polygon from a non-simple boundary line. Assuming valid geometric inputs allows functions to operate more efficiently, since they do not need to check for topological correctness. (Notable exceptions are that zero-length lines and polygons with inversions are generally handled correctly.) Also, most PostGIS functions produce valid geometry output if the inputs are valid. This allows PostGIS functions to be chained together safely.

If you encounter unexpected error messages when calling PostGIS functions (such as "GEOS Intersection() threw an error!"), you should first confirm that the function arguments are valid. If they are not, then consider using one of the techniques below to ensure the data you are processing is valid.

 If a function reports an error with valid inputs, then you may have found an error in either PostGIS or one of the libraries it uses, and you should report this to the PostGIS project. The same is true if a PostGIS function returns an invalid geometry for valid input.

To test if a geometry is valid use the ST_IsValid function:

```SELECT ST_IsValid('POLYGON ((20 180, 180 180, 180 20, 20 20, 20 180))');
-----------------
t
```

Information about the nature and location of an geometry invalidity are provided by the ST_IsValidDetail function:

```SELECT valid, reason, ST_AsText(location) AS location
FROM ST_IsValidDetail('POLYGON ((20 20, 120 190, 50 190, 170 50, 20 20))') AS t;

valid |      reason       |                  location
-------+-------------------+---------------------------------------------
f     | Self-intersection | POINT(91.51162790697674 141.56976744186045)
```

In some situations it is desirable to correct invalid geometry automatically. Use the ST_MakeValid function to do this. (`ST_MakeValid` is a case of a spatial function that does allow invalid input!)

By default, PostGIS does not check for validity when loading geometry, because validity testing can take a lot of CPU time for complex geometries. If you do not trust your data sources, you can enforce a validity check on your tables by adding a check constraint:

```ALTER TABLE mytable
CHECK (ST_IsValid(geom));```

## 4.5. SPATIAL_REF_SYS 테이블과 공간 참조 시스템

A Spatial Reference System (SRS) (also called a Coordinate Reference System (CRS)) defines how geometry is referenced to locations on the Earth's surface. There are three types of SRS:

• A geodetic SRS uses angular coordinates (longitude and latitude) which map directly to the surface of the earth.

• A projected SRS uses a mathematical projection transformation to "flatten" the surface of the spheroidal earth onto a plane. It assigns location coordinates in a way that allows direct measurement of quantities such as distance, area, and angle. The coordinate system is Cartesian, which means it has a defined origin point and two perpendicular axes (usually oriented North and East). Each projected SRS uses a stated length unit (usually metres or feet). A projected SRS may be limited in its area of applicability to avoid distortion and fit within the defined coordinate bounds.

• A local SRS is a Cartesian coordinate system which is not referenced to the earth's surface. In PostGIS this is specified by a SRID value of 0.

There are many different spatial reference systems in use. Common SRSes are standardized in the European Petroleum Survey Group EPSG database. For convenience PostGIS (and many other spatial systems) refers to SRS definitions using an integer identifier called a SRID.

A geometry is associated with a Spatial Reference System by its SRID value, which is accessed by ST_SRID. The SRID for a geometry can be assigned using ST_SetSRID. Some geometry constructor functions allow supplying a SRID (such as ST_Point and ST_MakeEnvelope). The EWKT format supports SRIDs with the `SRID=n;` prefix.

Spatial functions processing pairs of geometries (such as overlay and relationship functions) require that the input geometries are in the same spatial reference system (have the same SRID). Geometry data can be transformed into a different spatial reference system using ST_Transform and ST_TransformPipeline. Geometry returned from functions has the same SRS as the input geometries.

### 4.5.1. SPATIAL_REF_SYS Table

The `SPATIAL_REF_SYS` table used by PostGIS is an OGC-compliant database table that defines the available spatial reference systems. It holds the numeric SRIDs and textual descriptions of the coordinate systems.

`SPATIAL_REF_SYS` 테이블 정의는 다음과 같습니다:

```CREATE TABLE spatial_ref_sys (
srid       INTEGER NOT NULL PRIMARY KEY,
auth_name  VARCHAR(256),
auth_srid  INTEGER,
srtext     VARCHAR(2048),
proj4text  VARCHAR(2048)
)```

다음과 같은 명령행 옵션이 있습니다:

`srid`

데이터베이스 내부에서 공간 참조 시스템(SRS)을 고유하게 식별하는 정수값입니다.

`auth_name`

해당 참조 시스템을 위해 인용되는 표준 또는 표준들 본체의 명칭입니다. 예를 들어 "EPSG"는 유효한 `AUTH_NAME` 이라고 할 수 있습니다.

`auth_srid`

The ID of the Spatial Reference System as defined by the Authority cited in the `auth_name`. In the case of EPSG, this is the EPSG code.

`srtext`

공간 참조 시스템의 WKT(Well-Known Text) 표현식입니다. 다음은 WKT SRS 표현식의 예입니다:

```PROJCS["NAD83 / UTM Zone 10N",
DATUM["North_American_Datum_1983",
SPHEROID["GRS 1980",6378137,298.257222101]
],
PRIMEM["Greenwich",0],
UNIT["degree",0.0174532925199433]
],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-123],
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1]
]```

For a discussion of SRS WKT, see the OGC standard Well-known text representation of coordinate reference systems.

`proj4text`

PostGIS는 좌표 변환 기능을 제공하기 위해 proj4 라이브러리를 이용합니다. `PROJ4TEXT` 열이 특정 SRID에 대응하는 proj4 좌펴 정의 스트링을 담고 있습니다. 다음은 그 예입니다:

`+proj=utm +zone=10 +ellps=clrk66 +datum=NAD27 +units=m`

이에 대한 자세한 정보는 http://trac.osgeo.org/proj/ 주소의 proj4 웹사이트를 참조하십시오. `spatial_ref_sys.sql` 파일이 모든 EPSG 투영에 대한 `SRTEXT``PROJ4TEXT` 정의를 담고 있습니다.

When retrieving spatial reference system definitions for use in transformations, PostGIS uses fhe following strategy:

• If `auth_name` and `auth_srid` are present (non-NULL) use the PROJ SRS based on those entries (if one exists).

• If `srtext` is present create a SRS using it, if possible.

• If `proj4text` is present create a SRS using it, if possible.

### 4.5.2. SPATIAL_REF_SYS 테이블과 공간 참조 시스템

PostGIS의 `SPATIAL_REF_SYS` 테이블이 proj 라이브러리가 처리할 수 있는, 좀 더 널리 사용되는 공간 참조 시스템 3000여 개를 담고 있긴 하지만 현재까지 알려진 모든 공간 참조 시스템을 다 담고 있지는 않으며, 사용자가 proj4의 구조를 잘 알고 있다면 자기만의 사용자 지정 투영을 정의할 수도 있습니다. 공간 참조 시스템 대부분은 특정 지역에 특화되어 있으며, 특화된 지역 범위 바깥에서 사용할 경우 어떤 의미도 없다는 점을 명심하십시오.

핵심 `SPATIAL_REF_SYS` 테이블에 정의되지 않은 공간 참조 시스템은 http://spatialreference.org/ 에 훌륭하게 정리되어 있습니다.

좀 더 널리 사용되는 공간 참조 시스템에는 4326 - WGS 84 Long Lat, 4269 - NAD 83 Long Lat, 3395 - WGS 84 World Mercator, 2163 - US National Atlas Equal Area, 그리고 NAD 83 및 WGS 84 UTM 대(帶; zone)의 공간 참조 시스템이 있습니다. 각 UTM 대는 측정에 가장 이상적인 공간 참조 시스템이지만, 6도 범위의 지역에만 특화되어 있습니다.

미국 여러 주의 평면 공간 참조 시스템(미터 또는 피트 기반)은 각 주마다 보통 한 개 또는 두 개가 존재합니다. 미터 기반 공간 참조 시스템 대부분은 `SPATIAL_REF_SYS` 테이블에 들어 있지만, 피트 기반 또는 ESRI가 생성한 공간 참조 시스템 중 상당수는 사용자가 spatialreference.org 에서 찾아와야 합니다.

You can even define non-Earth-based coordinate systems, such as Mars 2000 This Mars coordinate system is non-planar (it's in degrees spheroidal), but you can use it with the `geography` type to obtain length and proximity measurements in meters instead of degrees.

Here is an example of loading a custom coordinate system using an unassigned SRID and the PROJ definition for a US-centric Lambert Conformal projection:

```INSERT INTO spatial_ref_sys (srid, proj4text)
VALUES ( 990000,
'+proj=lcc  +lon_0=-95 +lat_0=25 +lat_1=25 +lat_2=25 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs'
);
```

## 4.6. 공간 테이블 생성

### 4.6.1. 공간 테이블 생성

You can create a table to store geometry data using the CREATE TABLE SQL statement with a column of type `geometry`. The following example creates a table with a geometry column storing 2D (XY) LineStrings in the BC-Albers coordinate system (SRID 3005):

```CREATE TABLE roads (
id SERIAL PRIMARY KEY,
name VARCHAR(64),
geom geometry(LINESTRING,3005)
);```

The `geometry` type supports two optional type modifiers:

• 유형 변경자가 허용하는 값은 다음과 같습니다. POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON. 또 이 변경자는 Z, M 및 ZM이라는 접미사를 통해 차원수 제약도 지원합니다. 따라서, 예를 들자면 'LINESTRINGM'의 변경자는 3차원 이하의 라인 스트링만을 허용할 것이며, 세 번째 차원을 기준으로 취급할 것입니다. 마찬가지로 'POINTZM'은 네 가지 차원의 데이터를 입력해야 할 것입니다.

• the SRID modifier restricts the spatial reference system SRID to a particular number. If omitted, the SRID defaults to 0.

Examples of creating tables with geometry columns:

• Create a table holding any kind of geometry with the default SRID:

`CREATE TABLE geoms(gid serial PRIMARY KEY, geom geometry );`
• Create a table with 2D POINT geometry with the default SRID:

`CREATE TABLE pts(gid serial PRIMARY KEY, geom geometry(POINT) );`
• Create a table with 3D (XYZ) POINTs and an explicit SRID of 3005:

`CREATE TABLE pts(gid serial PRIMARY KEY, geom geometry(POINTZ,3005) );`
• Create a table with 4D (XYZM) LINESTRING geometry with the default SRID:

`CREATE TABLE lines(gid serial PRIMARY KEY, geom geometry(LINESTRINGZM) );`
• Create a table with 2D POLYGON geometry with the SRID 4267 (NAD 1927 long lat):

`CREATE TABLE polys(gid serial PRIMARY KEY, geom geometry(POLYGON,4267) );`

It is possible to have more than one geometry column in a table. This can be specified when the table is created, or a column can be added using the ALTER TABLE SQL statement. This example adds a column that can hold 3D LineStrings:

`ALTER TABLE roads ADD COLUMN geom2 geometry(LINESTRINGZ,4326);`

### 4.6.2. The GEOMETRY_COLUMNS VIEW

OpenGIS의 "SQL 용 단순 피처 사양서(Simple Features Specification for SQL)"는 표준 GIS 객체 유형, 그 유형들을 다루기 위해 필요한 함수, 그리고 메타데이터 테이블의 집합을 정의합니다. 메타데이터의 일관성을 유지하기 위해 공간 열 생성 및 삭제와 같은 작업은 OpenGIS가 정의한 특별한 과정을 거쳐 이루어집니다.

`\d geometry_columns`
```View "public.geometry_columns"
Column       |          Type          | Modifiers
-------------------+------------------------+-----------
f_table_catalog   | character varying(256) |
f_table_schema    | character varying(256) |
f_table_name      | character varying(256) |
f_geometry_column | character varying(256) |
coord_dimension   | integer                |
srid              | integer                |
type              | character varying(30)  |```

다음과 같은 명령행 옵션이 있습니다:

`f_table_catalog, f_table_schema, f_table_name`

도형 열을 담고 있는 피처 테이블의 조건을 완전히 만족하는 명칭입니다. "카탈로그"와 "스키마"가 오라클 용어라는 점을 주목하십시오. "카탈로그"를 대체하는 PostgreSQL 용어가 없기 때문에 해당 열은 공백으로 남게 됩니다. "스키마"의 경우 PostgreSQL 스키마 명칭이 사용됩니다(기본값은 `public` 입니다).

`f_geometry_column`

피처 테이블이 담고 있는 도형 열의 명칭입니다.

`coord_dimension`

열의 공간 차원(2, 3, 또는 4차원)입니다.

`srid`

해당 테이블이 담고 있는 도형의 좌표가 사용하는 공간 좌표 시스템의 ID로, `SPATIAL_REF_SYS` 를 참조하는 외래 키(foreign key)입니다.

`type`

공간 객체의 유형입니다. 공간 열을 단일 유형으로 제약하려면 다음 유형 가운데 하나를 이용하십시오. POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION 또는 이에 상응하는 XYM 버전의 POINTM, LINESTRINGM, POLYGONM, MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM. 혼합 유형 집합을 이용하려면 유형으로 "GEOMETRY"를 이용할 수 있습니다.

### 4.6.3. geometry_columns에 도형 열을 직접 등록하기

AddGeometryColumn() 함수를 쓸 수 없을 때 이런 일이 발생할 수 있는 두 가지 경우가 있는데, SQL 뷰 그리고 대규모 삽입(bulk insert)의 경우입니다. 이런 경우, 해당 열에 제약 조건을 걸어서 geometry_columns 테이블 등록을 바로잡을 수 있습니다. PostGIS 2.0 이상 버전에서는, 사용자 열이 typmod 기반이라면 생성 과정 중에 정확하게 등록할 것이기 때문에 아무것도 할 필요가 없다는 점을 기억하십시오.

```-- Lets say you have a view created like this
CREATE VIEW public.vwmytablemercator AS
SELECT gid, ST_Transform(geom, 3395) As geom, f_name
FROM public.mytable;

-- For it to register correctly
-- You need to cast the geometry
--
DROP VIEW public.vwmytablemercator;
CREATE VIEW  public.vwmytablemercator AS
SELECT gid, ST_Transform(geom, 3395)::geometry(Geometry, 3395) As geom, f_name
FROM public.mytable;

-- If you know the geometry type for sure is a 2D POLYGON then you could do
DROP VIEW public.vwmytablemercator;
CREATE VIEW  public.vwmytablemercator AS
SELECT gid, ST_Transform(geom,3395)::geometry(Polygon, 3395) As geom, f_name
FROM public.mytable;```
```--Lets say you created a derivative table by doing a bulk insert
SELECT poi.gid, poi.geom, citybounds.city_name
INTO myschema.my_special_pois
FROM poi INNER JOIN citybounds ON ST_Intersects(citybounds.geom, poi.geom);

-- Create 2D index on new table
CREATE INDEX idx_myschema_myspecialpois_geom_gist
ON myschema.my_special_pois USING gist(geom);

-- If your points are 3D points or 3M points,
-- then you might want to create an nd index instead of a 2D index
CREATE INDEX my_special_pois_geom_gist_nd
ON my_special_pois USING gist(geom gist_geometry_ops_nd);

-- To manually register this new table's geometry column in geometry_columns.
-- Note it will also change the underlying structure of the table to
-- to make the column typmod based.
SELECT populate_geometry_columns('myschema.my_special_pois'::regclass);

-- If you are using PostGIS 2.0 and for whatever reason, you
-- you need the constraint based definition behavior
-- (such as case of inherited tables where all children do not have the same type and srid)
-- set optional use_typmod argument to false
SELECT populate_geometry_columns('myschema.my_special_pois'::regclass, false); ```

구식 제약조건 기반 방법을 여전히 지원하긴 하지만, 뷰에서 직접적으로 사용되는 제약조건 기반 도형 열은 typmod 기반 열과는 달리 geometry_columns 테이블에 정확하게 등록되지 않을 겁니다. 다음은 typmod를 이용하는 열과 제약조건을 이용하는 또다른 열을 정의하는 예시입니다.

```CREATE TABLE pois_ny(gid SERIAL PRIMARY KEY, poi_name text, cat text, geom geometry(POINT,4326));
SELECT AddGeometryColumn('pois_ny', 'geom_2160', 2160, 'POINT', 2, false);```

PSQL에서 실행할 경우

`\d pois_ny;`

두 열이 서로 다르게 정의되었다는 사실을 알 수 있습니다. 하나는 typmod, 다른 하나는 제약조건으로 정의되었습니다.

```Table "public.pois_ny"
Column   |         Type          |                       Modifiers

-----------+-----------------------+------------------------------------------------------
gid       | integer               | not null default nextval('pois_ny_gid_seq'::regclass)
poi_name  | text                  |
cat       | character varying(20) |
geom      | geometry(Point,4326)  |
geom_2160 | geometry              |
Indexes:
"pois_ny_pkey" PRIMARY KEY, btree (gid)
Check constraints:
"enforce_dims_geom_2160" CHECK (st_ndims(geom_2160) = 2)
"enforce_geotype_geom_2160" CHECK (geometrytype(geom_2160) = 'POINT'::text
OR geom_2160 IS NULL)
"enforce_srid_geom_2160" CHECK (st_srid(geom_2160) = 2160)```

둘 다 geometry_columns 테이블에 정확하게 등록됩니다.

```SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns
WHERE f_table_name = 'pois_ny';```
```f_table_name | f_geometry_column | srid | type
-------------+-------------------+------+-------
pois_ny      | geom              | 4326 | POINT
pois_ny      | geom_2160         | 2160 | POINT```

하지만 -- 다음과 같은 뷰를 생성하려 한다면

```CREATE VIEW vw_pois_ny_parks AS
SELECT *
FROM pois_ny
WHERE cat='park';

SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns
WHERE f_table_name = 'vw_pois_ny_parks';```

typmod 기반 도형 열은 정확하게 등록되지만, 제약조건 기반 도형 열은 정확하게 등록되지 않습니다.

```f_table_name   | f_geometry_column | srid |   type
------------------+-------------------+------+----------
vw_pois_ny_parks | geom              | 4326 | POINT
vw_pois_ny_parks | geom_2160         |    0 | GEOMETRY```

PostGIS 향후 버전에서는 변경될 수도 있지만, 현재 버전에서 제약조건 기반 뷰 열을 정확하게 등록하려면 다음과 같이 해야 합니다:

```DROP VIEW vw_pois_ny_parks;
CREATE VIEW vw_pois_ny_parks AS
SELECT gid, poi_name, cat,
geom,
geom_2160::geometry(POINT,2160) As geom_2160
FROM pois_ny
WHERE cat = 'park';
SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns
WHERE f_table_name = 'vw_pois_ny_parks';```
```f_table_name   | f_geometry_column | srid | type
------------------+-------------------+------+-------
vw_pois_ny_parks | geom              | 4326 | POINT
vw_pois_ny_parks | geom_2160         | 2160 | POINT```

## 4.7. GIS (벡터) 데이터 로드

공간 테이블 생성을 끝냈다면, 사용자가 데이터베이스에 GIS 데이터를 업로드할 준비가 된 것입니다. 현재, 형식화된 SQL 구문을 사용하거나 shapefile 로더/덤퍼를 사용하는 두 가지 방법으로 PostGIS/PostgreSQL 데이터베이스에 데이터를 입력할 수 있습니다.

### 4.7.1. SQL을 이용해 데이터 가져오기

사용자 데이터를 텍스트 표현식으로 변환할 수 있다면, PostGIS에 사용자 데이터를 입력하는 가장 쉬운 방법은 형식화된(formatted) SQL을 이용하는 것입니다. Oracle이나 다른 SQL 데이터베이스와 마찬가지로, SQL 터미널 모니터에 SQL "INSERT" 선언문으로 가득 찬 대용량 텍스트 파일을 송신하는(piping) 방법으로 데이터를 일괄 로드시킬 수 있습니다.

데이터 업로드 파일(예를 들어 `roads.sql`)은 다음처럼 보일 것입니다:

```BEGIN;
VALUES (1,'LINESTRING(191232 243118,191108 243242)','Jeff Rd');
VALUES (2,'LINESTRING(189141 244158,189265 244817)','Geordie Rd');
VALUES (3,'LINESTRING(192783 228138,192612 229814)','Paul St');
VALUES (4,'LINESTRING(189412 252431,189631 259122)','Graeme Ave');
VALUES (5,'LINESTRING(190131 224148,190871 228134)','Phil Tce');
VALUES (6,'LINESTRING(198231 263418,198213 268322)','Dave Cres');
COMMIT;```

"psql" SQL 터미널 모니터를 이용해서 PostgreSQL로 데이터 파일을 매우 쉽게 송신할 수 있습니다.

`psql -d [database] -f roads.sql`

### 4.7.2. shp2pgsql: ESRI shapefile 로더 이용하기

`shp2pgsql` 데이터 로더는 ESRI shapefile을, 도형 형식이든 지리형 형식이든, PostGIS/PostgreSQL 데이터베이스로 삽입하기에 적합한 SQL로 변환합니다. 이 로더에는 명령행(command line) 플래그로 구별되는 몇 가지 실행 모드가 존재합니다.

shp2pgsql 명령행 로더 외에, 사용자가 PostGIS를 처음 접하는 경우 스크립트를 사용하지 않고 단 한 번 로드하는 데 더 쉽게 사용할 수 있을 뿐만 아니라 명령행 로더가 가진 대부분의 옵션도 가지고 있는 `shp2pgsql-gui` 그래픽 인터페이스도 있습니다. `shp2pgsql-gui`를 pgAdmin III의 플러그인으로 설정할 수도 있습니다.

c|a|d|p -- 이들은 상호배타적인 옵션들입니다:

`-c`

새 테이블을 생성한 다음 shapefile의 데이터로 해당 테이블을 채웁니다. 이것이 기본 모드입니다.

`-a`

기존 데이터베이스 테이블에 shapefile의 데이터를 추가합니다. 이 옵션을 이용해서 복수의 파일을 로드하려면, 파일들이 동일한 속성 및 동일한 데이터 유형을 담고 있어야 한다는 점을 주의하십시오.

`-d`

기존 데이터베이스 테이블을 삭제(drop)한 다음 shapefile의 데이터를 가진 새 테이블을 생성합니다.

`-p`

테이블을 생성하는 SQL 코드만 생성하고, 어떤 실제 데이터도 추가하지 않습니다. 테이블 생성과 데이터 로드 단계를 완전히 분리해야 할 경우 사용할 수 있습니다.

`-?`

도움말 화면을 표출합니다.

`-D`

산출물 데이터의 형식으로 PostgreSQL "덤프(dump)" 형식을 사용합니다. 이 옵션은 -a, -c 및 -d와 함께 사용할 수 있습니다. 이 덤프 형식은 기본 "삽입" SQL 형식보다 훨씬 빨리 로드할 수 있습니다. 대용량 데이터셋의 경우 이 옵션을 사용하십시오.

`-s [<FROM_SRID>:]<SRID>`

도형 테이블을 생성하고 지정된 SRID로 채웁니다. 입력 shapefile이 주어진 FROM_SRID를 쓰도록 설정하는 옵션도 있습니다. 이런 경우 도형이 목표 SRID로 재투영될 것입니다. FROM_SRID는 -D 옵션과 함께 사용될 수 없습니다.

`-k`

식별자의 대소문자(열, 스키마 및 속성)를 유지합니다. shapefile 안의 속성은 모두 대문자라는 점을 주의하십시오.

`-i`

DBF 헤더 서명이 64비트 bigint 형식을 보장하더라도, 모든 정수를 표준 32비트 정수로 강제 변환하고 64비트 bigint 형식을 생성하지 않습니다.

`-I`

도형 열에 GiST 인덱스를 생성합니다.

`-m`

"-m `파일명`" 형식으로 (긴) 열 명칭과 10문자 DBF 열 명칭을 매핑하는 목록을 담은 파일을 지정합니다. 이 파일의 내용은 공백으로 구분된 두 명칭으로 이루어진 하나 이상의 행으로, 행 맨 앞과 맨 뒤에는 공백이 없어야 합니다. 다음은 그 예시입니다:

```COLUMNNAME DBFFIELD1
AVERYLONGCOLUMNNAME DBFFIELD2```

`-S`

다중(multi) 도형 대신 단순 도형을 생성합니다. 이 옵션은 모든 도형이 실제로 단일형(예: 단일 외곽선을 가진 다중 폴리곤 또는 단일 꼭짓점을 가진 다중 포인트)일 경우에만 작동합니다.

`-t <dimensionality>`

산출 도형이 지정된 차원수를 가지도록 강제합니다. 차원수를 지시하는 데 다음 스트링을 사용하십시오: 2D, 3DZ, 3DM, 4D

입력물이 지정된 차원수보다 낮은 차원일 경우, 출력물의 해당 차원은 0으로 채워질 것입니다. 입력물이 지정된 차원수보다 높은 차원일 경우, 필요 없는 차원은 제거될 것입니다.

`-w`

WKB 대신 WKT 형식으로 출력합니다. 정확도가 부족하기 때문에 좌표가 이동될 가능성이 있다는 점을 주의하십시오.

`-e`

각 선언문을 상호처리를 이용하지 않고 자체적으로 실행합니다. 오류를 생성하는 몇몇 망가진 도형이 있을 경우 이 옵션을 사용하면 괜찮은 데이터 대다수를 로드할 수 있습니다. "덤프" 형식은 항상 상호처리를 이용하기 때문에 -D 플래그와 함께 사용할 수 없다는 점을 주의하십시오.

`-W <encoding>`

입력 데이터(DBF 파일)의 인코딩을 지정합니다. 이 옵션을 사용하면, DBF의 모든 속성을 지정된 인코딩에서 UTF8로 변환합니다. 그 결과로 생성되는 SQL 출력물은 `SET CLIENT_ENCODING to UTF8` 명령어를 담게 되어, 백엔드에서 UTF8을 데이터베이스 내부에서 이용하도록 설정된 어떤 인코딩으로든 재변환할 수 있습니다.

`-N <policy>`

NULL 도형 처리 방침 -- insert*(상관없이 삽입), skip(건너뛰기), abort(중단)

`-n`

DBF 파일만 임포트합니다. 사용자 데이터에 대응하는 shapefile이 없다면, 자동적으로 이 모드로 전환하여 DBF만 로드할 것입니다. 따라서 전체 shapefile 집합을 가지고 있지만 도형을 빼고 속성 데이터만 필요한 경우에만 이 플래그를 설정해야 합니다.

`-G`

(경도/위도가 필요한) 도형 대신 WGS84 경위도(SRID=4326)를 쓰는 지리형을 이용합니다.

`-T <tablespace>`

새 테이블을 위한 테이블스페이스를 지정합니다. -X 파라미터가 함께 쓰인 경우가 아니라면 여전히 인덱스가 기본 테이블스페이스를 이용할 것입니다. PostgreSQL 문서는 사용자 지정 테이블스페이스가 필요한 경우를 잘 설명하고 있습니다.

`-X <tablespace>`

새 테이블의 인덱스를 위한 테이블스페이스를 지정합니다. 이 옵션은 기본 키(primary key) 인덱스에 적용되며, -I 플래그를 함께 사용하는 경우 GiST 공간 인덱스에도 적용됩니다.

`-Z`

When used, this flag will prevent the generation of `ANALYZE` statements. Without the -Z flag (default behavior), the `ANALYZE` statements will be generated.

다음은 로더를 이용해서 입력 파일을 생성하고 업로드하는 세션의 예시입니다:

```# shp2pgsql -c -D -s 4269 -i -I shaperoads.shp myschema.roadstable
```

UNIX 파이프(pipe)를 이용하면 모든 변환 및 업로드 작업을 한 번에 끝낼 수 있습니다:

`# shp2pgsql shaperoads.shp myschema.roadstable | psql -d roadsdb`

## 4.8. 공간 테이블 생성

SQL이나 shapefile 로더/덤퍼를 이용해서 데이터베이스로부터 데이터를 추출할 수 있습니다. SQL 단원에서 공간 테이블에 대한 비교 및 쿼리를 할 수 있는 몇몇 연산자에 대해 논의할 것입니다.

### 4.8.1. SQL을 이용해 데이터 가져오기

데이터베이스로부터 데이터를 추출하는 가장 간단한 방법은 SQL 선별(select) 쿼리로 반환될 레코드 및 열의 개수를 줄인 다음 해당 결과 열을 파싱 가능한 텍스트 파일로 덤프받는 것입니다:

```db=# SELECT road_id, ST_AsText(road_geom) AS geom, road_name FROM roads;

--------+-----------------------------------------+-----------
1 | LINESTRING(191232 243118,191108 243242) | Jeff Rd
2 | LINESTRING(189141 244158,189265 244817) | Geordie Rd
3 | LINESTRING(192783 228138,192612 229814) | Paul St
4 | LINESTRING(189412 252431,189631 259122) | Graeme Ave
5 | LINESTRING(190131 224148,190871 228134) | Phil Tce
6 | LINESTRING(198231 263418,198213 268322) | Dave Cres
7 | LINESTRING(218421 284121,224123 241231) | Chris Way
(6 rows)```

하지만, 반환되는 필드의 개수를 줄이기 위해 어떤 종류의 제약이 필요할 때가 있을 것입니다. 속성 기반 제약의 경우, 일반적인 비공간 테이블의 경우와 동일한 SQL 문법을 쓰면 됩니다. 공간 제약의 경우, 다음 유용한 연산자들을 쓸 수 있습니다.

`ST_Intersects`

This function tells whether two geometries share any space.

`=`

이 연산자는 두 도형이 기하학적으로 동일한지를 테스트합니다.예를 들어, 'POLYGON((0 0,1 1,1 0,0 0))'과 'POLYGON((0 0,1 1,1 0,0 0))'이 동일한지를 말입니다(동일합니다).

다음으로, 이 연산자들을 쿼리에 쓸 수 있습니다. SQL 명령행에 도형과 경계 상자를 지정할 때, "ST_GeomFromText()" 함수를 이용해서 스트링 표현식을 도형으로 정확하게 변환시켜야 합니다. 해당 데이터와 일치하는 가공의 공간 참조 시스템은 312입니다. 다음은 그 예시입니다:

```SELECT road_id, road_name

이 쿼리는 해당 값과 동일한 도형을 담고 있는 "ROADS_GEOM" 테이블로부터 단일 레코드를 반환할 것입니다.

To check whether some of the roads passes in the area defined by a polygon:

```SELECT road_id, road_name

가장 흔한 공간 쿼리는 아마도 데이터 브라우저 또는 웹 매퍼 같은 클라이언트 소프트웨어가 화면 표출을 위해 "맵 프레임(map frame)" 용량에 해당하는 데이터를 가져오기 위해 사용하는 "프레임 기반(frame-based)" 쿼리일 것입니다.

"&&" 연산자 사용시, 비교 피처로 BOX3D 또는 도형을 지정할 수 있습니다. 하지만 도형을 지정했을 경우, 비교 작업에 해당 경계 상자가 사용될 것입니다.

Using a "BOX3D" object for the frame, such a query looks like this:

```SELECT ST_AsText(roads_geom) AS geom
WHERE
```

화면에 해당하는 데이터의 투영체를 지정하는 데 SRID 312를 썼다는 사실에 주의하십시오.

### 4.8.2. 덤퍼 이용하기

`pgsql2shp` 테이블 덤퍼는 데이터베이스에 직접 연결되어 (아마도 쿼리가 정의했을) 테이블을 shapefile로 변환합니다. 기본 문법은 다음과 같습니다:

```pgsql2shp [<options
>] <database
> [<schema
>.]<table>
```
```pgsql2shp [<options
>] <database
> <query>
```

다음과 같은 명령행 옵션이 있습니다:

`-f <filename>`

특정 파일명으로 출력물을 작성합니다.

`-h <host>`

연결할 데이터베이스 호스트를 설정합니다.

`-p <port>`

데이터베이스 호스트 연결시 사용할 포트를 설정합니다.

`-P <password>`

데이터베이스 연결에 사용할 비밀번호를 설정합니다.

`-u <user>`

데이터베이스 연결에 사용할 사용자명을 설정합니다.

`-g <geometry column>`

복수의 도형 열을 가진 테이블일 경우, shapefile 작성에 이용될 도형 열을 설정합니다.

`-b`

바이너리 커서를 사용하도록 설정합니다. 이 옵션을 쓰면 실행 속도가 빨라지지만, 테이블 안에 있는 비(非) 도형 속성 가운데 하나라도 텍스트로 작성할 캐스트(cast)가 부족할 경우 실행되지 않을 것입니다.

`-r`

로(raw) 모드입니다. `gid` 필드를 삭제하거나, 열 명칭을 제외하지 않습니다.

`-m filename`

식별자를 10문자 명칭으로 다시 매핑(remap)합니다. 해당 파일의 내용은 공백으로 구분된 두 심볼로 이루어진 복수의 행으로, 행 맨 앞과 맨 뒤에는 공백이 없어야 합니다. VERYLONGSYMBOL SHORTONE ANOTHERVERYLONGSYMBOL SHORTER 등과 같은 예가 있습니다.

## 4.9. 인덱스 빌드 작업

인덱스 덕분에 공간 데이터베이스가 대용량 데이터셋을 사용할 수 있습니다. 인덱스 작업을 하지 않으면, 어떤 피처를 검색하든 데이터베이스 안의 모든 레코드를 "순차 스캔"해야 할 것입니다. 인덱스 작업은 데이터를 특정 레코드를 찾기 위해 빠르게 훑어갈 수 있는 검색 트리로 조직해서 검색 속도를 향상시킵니다. PostgreSQL는 기본적으로 B-Tree, R-Tree, GiST 세 종류의 인덱스를 지원합니다.

The B-tree index method commonly used for attribute data is not very useful for spatial data, since it only supports storing and querying data in a single dimension. Data such as geometry (which has 2 or more dimensions) requires an index method that supports range query across all the data dimensions. One of the key advantages of PostgreSQL for spatial data handling is that it offers several kinds of index methods which work well for multi-dimensional data: GiST, BRIN and SP-GiST indexes.

• GiST(Generalized Search Tree) 인덱스는 데이터를 "한 쪽에 있는 것", "겹치는 것", "내부에 있는 것"으로 분해하며 GIS 데이터를 포함한 광범위한 데이터 유형에 쓰일 수 있습니다. PostGIS는 GiST를 써서 GIS 데이터에 인덱스 작업을 한 다음, 해당 데이터에 다시 작업된 R-Tree 인덱스를 이용합니다.

• BRIN (Block Range Index) indexes operate by summarizing the spatial extent of ranges of table records. Search is done via a scan of the ranges. BRIN is only appropriate for use for some kinds of data (spatially sorted, with infrequent or no update). But it provides much faster index create time, and much smaller index size.

• SP-GiST (Space-Partitioned Generalized Search Tree) is a generic index method that supports partitioned search trees such as quad-trees, k-d trees, and radix trees (tries).

Spatial indexes store only the bounding box of geometries. Spatial queries use the index as a primary filter to quickly determine a set of geometries potentially matching the query condition. Most spatial queries require a secondary filter that uses a spatial predicate function to test a more specific spatial condition. For more information on queying with spatial predicates see Section 5.2, “Using Spatial Indexes”.

See also the PostGIS Workshop section on spatial indexes, and the PostgreSQL manual.

### 4.9.1. GiST 인덱스

GiST는 "일반화된 검색 트리"의 줄임말로, 인덱스 작업의 포괄적인 형태입니다. GIS 인덱스 작업 외에도, 일반 B-Tree 인덱스 작업으로는 쓸 수 없는 온갖 종류의 비정규 데이터 구조(정수 배열, 분광 데이터 등등)에 대한 검색 속도를 향상시키는 데 GiST를 이용합니다.

GIS 데이터 테이블이 수천 행을 넘게 되면, 데이터 공간 검색의 속도를 향상시키기 위해 인덱스를 빌드하고 싶게 될 것입니다(사용자의 모든 검색이 속성에 기반하는 경우가 아니라면 말입니다. 그런 경우, 속성 필드에 대해 일반 인덱스를 빌드하면 됩니다).

"도형" 열에 대해 GiST 인덱스를 빌드하는 데 필요한 문법은 다음과 같습니다:

`CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] ); `

이 문법은 항상 2D 인덱스를 빌드할 것입니다. 해당 도형 유형에 PostGIS 2.0 이상 버전이 지원하는 n차원 인덱스를 얻으려면, 다음 문법으로 생성할 수 있습니다:

`CREATE INDEX [indexname] ON [tablename] USING GIST ([geometryfield] gist_geometry_ops_nd);`

Building a spatial index is a computationally intensive exercise. It also blocks write access to your table for the time it creates, so on a production system you may want to do in in a slower CONCURRENTLY-aware way:

`CREATE INDEX CONCURRENTLY [indexname] ON [tablename] USING GIST ( [geometryfield] ); `

After building an index, it is sometimes helpful to force PostgreSQL to collect table statistics, which are used to optimize query plans:

`VACUUM ANALYZE [table_name] [(column_name)];`

### 4.9.2. GiST 인덱스

BRIN stands for "Block Range Index". It is a general-purpose index method introduced in PostgreSQL 9.5. BRIN is a lossy index method, meaning that a secondary check is required to confirm that a record matches a given search condition (which is the case for all provided spatial indexes). It provides much faster index creation and much smaller index size, with reasonable read performance. Its primary purpose is to support indexing very large tables on columns which have a correlation with their physical location within the table. In addition to spatial indexing, BRIN can speed up searches on various kinds of attribute data structures (integer, arrays etc). For more information see the PostgreSQL manual.

GIS 데이터 테이블이 수천 행을 넘게 되면, 데이터 공간 검색의 속도를 향상시키기 위해 인덱스를 빌드하고 싶게 될 것입니다(사용자의 모든 검색이 속성에 기반하는 경우가 아니라면 말입니다. 그런 경우, 속성 필드에 대해 일반 인덱스를 빌드하면 됩니다).

A BRIN index stores the bounding box enclosing all the geometries contained in the rows in a contiguous set of table blocks, called a block range. When executing a query using the index the block ranges are scanned to find the ones that intersect the query extent. This is efficient only if the data is physically ordered so that the bounding boxes for block ranges have minimal overlap (and ideally are mutually exclusive). The resulting index is very small in size, but is typically less performant for read than a GiST index over the same data.

Building a BRIN index is much less CPU-intensive than building a GiST index. It's common to find that a BRIN index is ten times faster to build than a GiST index over the same data. And because a BRIN index stores only one bounding box for each range of table blocks, it's common to use up to a thousand times less disk space than a GiST index.

You can choose the number of blocks to summarize in a range. If you decrease this number, the index will be bigger but will probably provide better performance.

For BRIN to be effective, the table data should be stored in a physical order which minimizes the amount of block extent overlap. It may be that the data is already sorted appropriately (for instance, if it is loaded from another dataset that is already sorted in spatial order). Otherwise, this can be accomplished by sorting the data by a one-dimensional spatial key. One way to do this is to create a new table sorted by the geometry values (which in recent PostGIS versions uses an efficient Hilbert curve ordering):

```CREATE TABLE table_sorted AS
SELECT * FROM table  ORDER BY geom;
```

Alternatively, data can be sorted in-place by using a GeoHash as a (temporary) index, and clustering on that index:

```CREATE INDEX idx_temp_geohash ON table
USING btree (ST_GeoHash( ST_Transform( geom, 4326 ), 20));
CLUSTER table USING idx_temp_geohash;
```

"도형" 열에 대해 GiST 인덱스를 빌드하는 데 필요한 문법은 다음과 같습니다:

`CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geome_col] ); `

이 문법은 항상 2D 인덱스를 빌드할 것입니다. 해당 도형 유형에 PostGIS 2.0 이상 버전이 지원하는 n차원 인덱스를 얻으려면, 다음 문법으로 생성할 수 있습니다:

```CREATE INDEX [indexname] ON [tablename]
USING BRIN ([geome_col] brin_geometry_inclusion_ops_3d);```

You can also get a 4D-dimensional index using the 4D operator class:

```CREATE INDEX [indexname] ON [tablename]
USING BRIN ([geome_col] brin_geometry_inclusion_ops_4d);```

The above commands use the default number of blocks in a range, which is 128. To specify the number of blocks to summarise in a range, use this syntax

```CREATE INDEX [indexname] ON [tablename]
USING BRIN ( [geome_col] ) WITH (pages_per_range = [number]); ```

Keep in mind that a BRIN index only stores one index entry for a large number of rows. If your table stores geometries with a mixed number of dimensions, it's likely that the resulting index will have poor performance. You can avoid this performance penalty by choosing the operator class with the least number of dimensions of the stored geometries

"도형" 열에 대해 GiST 인덱스를 빌드하는 데 필요한 문법은 다음과 같습니다:

`CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geog_col] ); `

이 문법은 항상 2D 인덱스를 빌드할 것입니다. 해당 도형 유형에 PostGIS 2.0 이상 버전이 지원하는 n차원 인덱스를 얻으려면, 다음 문법으로 생성할 수 있습니다:

Currently, only "inclusion support" is provided, meaning that just the `&&`, `~` and `@` operators can be used for the 2D cases (for both `geometry` and `geography`), and just the `&&&` operator for 3D geometries. There is currently no support for kNN searches.

An important difference between BRIN and other index types is that the database does not maintain the index dynamically. Changes to spatial data in the table are simply appended to the end of the index. This will cause index search performance to degrade over time. The index can be updated by performing a `VACUUM`, or by using a special function `brin_summarize_new_values(regclass)`. For this reason BRIN may be most appropriate for use with data that is read-only, or only rarely changing. For more information refer to the manual.

To summarize using BRIN for spatial data:

• Index build time is very fast, and index size is very small.

• Index query time is slower than GiST, but can still be very acceptable.

• Requires table data to be sorted in a spatial ordering.

• Requires manual index maintenance.

• Most appropriate for very large tables, with low or no overlap (e.g. points), which are static or change infrequently.

• More effective for queries which return relatively large numbers of data records.

### 4.9.3. GiST 인덱스

SP-GiST stands for "Space-Partitioned Generalized Search Tree" and is a generic form of indexing for multi-dimensional data types that supports partitioned search trees, such as quad-trees, k-d trees, and radix trees (tries). The common feature of these data structures is that they repeatedly divide the search space into partitions that need not be of equal size. In addition to spatial indexing, SP-GiST is used to speed up searches on many kinds of data, such as phone routing, ip routing, substring search, etc. For more information see the PostgreSQL manual.

As it is the case for GiST indexes, SP-GiST indexes are lossy, in the sense that they store the bounding box enclosing spatial objects. SP-GiST indexes can be considered as an alternative to GiST indexes.

GIS 데이터 테이블이 수천 행을 넘게 되면, 데이터 공간 검색의 속도를 향상시키기 위해 인덱스를 빌드하고 싶게 될 것입니다(사용자의 모든 검색이 속성에 기반하는 경우가 아니라면 말입니다. 그런 경우, 속성 필드에 대해 일반 인덱스를 빌드하면 됩니다).

`CREATE INDEX [indexname] ON [tablename] USING SPGIST ( [geometryfield] ); `

이 문법은 항상 2D 인덱스를 빌드할 것입니다. 해당 도형 유형에 PostGIS 2.0 이상 버전이 지원하는 n차원 인덱스를 얻으려면, 다음 문법으로 생성할 수 있습니다:

`CREATE INDEX [indexname] ON [tablename] USING SPGIST ([geometryfield] spgist_geometry_ops_3d);`

Building a spatial index is a computationally intensive operation. It also blocks write access to your table for the time it creates, so on a production system you may want to do in in a slower CONCURRENTLY-aware way:

`CREATE INDEX CONCURRENTLY [indexname] ON [tablename] USING SPGIST ( [geometryfield] ); `

After building an index, it is sometimes helpful to force PostgreSQL to collect table statistics, which are used to optimize query plans:

`VACUUM ANALYZE [table_name] [(column_name)];`

An SP-GiST index can accelerate queries involving the following operators:

• <<, &<, &>, >>, <<|, &<|, |&>, |>>, &&, @>, <@, and ~=, for 2-dimensional indexes,

• &/&, ~==, @>>, and <<@, for 3-dimensional indexes.

There is no support for kNN searches at the moment.

### 4.9.4. 인덱스 빌드 작업

일반적인 경우라면 인덱스는 눈에 보이지 않게 데이터 접속 속도를 향상시킵니다. 인덱스가 빌드된 후, 쿼리 설계자는 쿼리 설계의 속도를 향상기키는 데 언제 인덱스 정보를 사용할 것인지 투명하게 결정합니다. 안타깝게도 PostgreSQL 쿼리 설계자가 GiST 인덱스의 사용을 제대로 최적화시키지 못 하기 때문에, 종종 공간 인덱스를 활용해야 할 검색이 대신 기본값인 전체 데이터의 순차 스캔을 이용할 때가 있습니다.

사용자의 공간 인덱스가 (또는 사용자의 속성 인덱스가) 활용되지 않고 있다는 사실을 알게 되었다면, 몇 가지 해결 방법이 있습니다:

• Examine the query plan and check your query actually computes the thing you need. An erroneous JOIN, either forgotten or to the wrong table, can unexpectedly retrieve table records multiple times. To get the query plan, execute with `EXPLAIN` in front of the query.

• Make sure statistics are gathered about the number and distributions of values in a table, to provide the query planner with better information to make decisions around index usage. VACUUM ANALYZE will compute both.

You should regularly vacuum your databases anyways. Many PostgreSQL DBAs run VACUUM as an off-peak cron job on a regular basis.

• 두 번째, 빈공간 분석으로 해결이 안 될 경우 SET ENABLE_SEQSCAN=OFF 명령어를 통해 강제로 쿼리 설계자가 인덱스 정보를 이용하도록 할 수 있습니다. 이 명령어는 공간 인덱스 쿼리일 경우에 한해 드물게 이용해야 합니다. 일반적으로, 쿼리 설계자는 언제 일반 B-Tree 인덱스를 활용해야 하는지 사용자보다 더 잘 알고 있습니다. 사용자 쿼리 실행 후, 다른 쿼리가 평소처럼 쿼리 설계자를 활용하도록 `ENABLE_SEQSCAN` 을 다시 켤지 고려해봐야 합니다.

• 쿼리 설계자가 순차 및 인덱스 스캔의 경중(cost)을 잘못 판단하고 있다면, postgresql.conf 파일의 random_page_cost의 값을 줄여보거나 "SET random_page_cost=#"로 써보십시오. 해당 파라미터의 기본값은 4이지만, 1또는 2로 설정해보십시오. 값을 감소시킬수록 점점 더 쿼리 설계자가 인덱스 스캔을 활용하게 될 것입니다.

• If SET ENABLE_SEQSCAN TO OFF; does not help your query, the query may be using a SQL construct that the Postgres planner is not yet able to optimize. It may be possible to rewrite the query in a way that the planner is able to handle. For example, a subquery with an inline SELECT may not produce an efficient plan, but could possibly be rewritten using a LATERAL JOIN.