OGG 已修改 . 還原成這個修訂版本
1 file changed, 237 insertions
shp2pgsql_copy.md(檔案已創建)
| @@ -0,0 +1,237 @@ | |||
| 1 | + | `shp2pgsql`의 COPY 동작 방식에 대해 자세히 설명하겠습니다. | |
| 2 | + | ||
| 3 | + | ## 🔍 **COPY 모드(-D) 동작 방식** | |
| 4 | + | ||
| 5 | + | ### **1. 기본 동작 원리** | |
| 6 | + | ```bash | |
| 7 | + | shp2pgsql -D -W "UTF-8" -s 4326 data.shp public.roads | |
| 8 | + | ``` | |
| 9 | + | ||
| 10 | + | **`-D` 옵션의 효과:** | |
| 11 | + | - **INSERT 문 대신 COPY 문 생성** | |
| 12 | + | - **PostgreSQL의 COPY 명령어 사용** | |
| 13 | + | - **배치 처리로 대량 데이터 최적화** | |
| 14 | + | ||
| 15 | + | ### **2. INSERT vs COPY 비교** | |
| 16 | + | ||
| 17 | + | #### **INSERT 모드 (기본)** | |
| 18 | + | ```sql | |
| 19 | + | -- shp2pgsql이 생성하는 SQL | |
| 20 | + | INSERT INTO public.roads (gid, name, geom) VALUES (1, 'Main St', ST_GeomFromText('LINESTRING(...)', 4326)); | |
| 21 | + | INSERT INTO public.roads (gid, name, geom) VALUES (2, 'Oak Ave', ST_GeomFromText('LINESTRING(...)', 4326)); | |
| 22 | + | INSERT INTO public.roads (gid, name, geom) VALUES (3, 'Pine Rd', ST_GeomFromText('LINESTRING(...)', 4326)); | |
| 23 | + | -- ... 수천/수만 개의 INSERT 문 | |
| 24 | + | ``` | |
| 25 | + | ||
| 26 | + | #### **COPY 모드 (-D 옵션)** | |
| 27 | + | ```sql | |
| 28 | + | -- shp2pgsql이 생성하는 SQL | |
| 29 | + | COPY public.roads (gid, name, geom) FROM STDIN; | |
| 30 | + | 1 Main St LINESTRING(...) | |
| 31 | + | 2 Oak Ave LINESTRING(...) | |
| 32 | + | 3 Pine Rd LINESTRING(...) | |
| 33 | + | -- ... 탭으로 구분된 데이터 | |
| 34 | + | \. | |
| 35 | + | ``` | |
| 36 | + | ||
| 37 | + | ## ⚡ **COPY 모드의 성능 우위** | |
| 38 | + | ||
| 39 | + | ### **3. 성능 차이 원인** | |
| 40 | + | ||
| 41 | + | | 구분 | INSERT | COPY | | |
| 42 | + | |------|--------|------| | |
| 43 | + | | **트랜잭션** | 각 INSERT마다 개별 | 단일 트랜잭션 | | |
| 44 | + | | **WAL 로깅** | 각 행마다 로그 | 배치 로그 | | |
| 45 | + | | **인덱스 업데이트** | 실시간 | 배치 후 | | |
| 46 | + | | **메모리 사용** | 높음 | 낮음 | | |
| 47 | + | | **처리 속도** | 느림 | **10-100배 빠름** | | |
| 48 | + | ||
| 49 | + | ### **4. COPY 모드의 내부 동작** | |
| 50 | + | ||
| 51 | + | ```bash | |
| 52 | + | # 1단계: SHP 파일 파싱 | |
| 53 | + | shp2pgsql이 .shp, .dbf 파일을 읽어서 구조 분석 | |
| 54 | + | ||
| 55 | + | # 2단계: COPY SQL 생성 | |
| 56 | + | 테이블 구조에 맞는 COPY 문장 생성 | |
| 57 | + | ||
| 58 | + | # 3단계: 데이터 스트리밍 | |
| 59 | + | PostgreSQL로 데이터를 직접 스트리밍 전송 | |
| 60 | + | ||
| 61 | + | # 4단계: 배치 처리 | |
| 62 | + | PostgreSQL이 내부적으로 배치 단위로 처리 | |
| 63 | + | ``` | |
| 64 | + | ||
| 65 | + | ## ��️ **COPY 모드의 데이터 처리 흐름** | |
| 66 | + | ||
| 67 | + | ### **5. 단계별 처리 과정** | |
| 68 | + | ||
| 69 | + | ``` | |
| 70 | + | SHP 파일 → shp2pgsql 파싱 → COPY SQL 생성 → PostgreSQL COPY 명령 → 데이터베이스 적재 | |
| 71 | + | ↓ ↓ ↓ ↓ ↓ | |
| 72 | + | Shapefile 구조 분석 COPY 문장 배치 처리 테이블 저장 | |
| 73 | + | ``` | |
| 74 | + | ||
| 75 | + | ### **6. 메모리 효율성** | |
| 76 | + | ||
| 77 | + | ```bash | |
| 78 | + | # INSERT 모드: 각 행마다 메모리 할당/해제 | |
| 79 | + | INSERT INTO table VALUES (...); # 메모리 사용 | |
| 80 | + | INSERT INTO table VALUES (...); # 메모리 사용 | |
| 81 | + | INSERT INTO table VALUES (...); # 메모리 사용 | |
| 82 | + | ||
| 83 | + | ||
| 84 | + | ... | |
| 85 | + | ||
| 86 | + | Let me reevaluate and take a different approach. | |
| 87 | + | ||
| 88 | + | _(It may take a moment for the assistant to restart.)_ | |
| 89 | + | ||
| 90 | + | ||
| 91 | + | ||
| 92 | + | _(It may take a moment for the assistant to restart.)_ | |
| 93 | + | ||
| 94 | + | ||
| 95 | + | ||
| 96 | + | `shp2pgsql`의 COPY 모드(`-D`) 동작 방식을 자세히 설명드리겠습니다. | |
| 97 | + | ||
| 98 | + | ## 🔄 **COPY 모드(-D) 동작 원리** | |
| 99 | + | ||
| 100 | + | ### **1. 기본 개념** | |
| 101 | + | ```bash | |
| 102 | + | # 일반 INSERT 모드 | |
| 103 | + | shp2pgsql -W "UTF-8" -s 4326 data.shp public.roads | |
| 104 | + | ||
| 105 | + | # COPY 모드 (-D 옵션) | |
| 106 | + | shp2pgsql -D -W "UTF-8" -s 4326 data.shp public.roads | |
| 107 | + | ``` | |
| 108 | + | ||
| 109 | + | ## 📋 **INSERT vs COPY 출력 비교** | |
| 110 | + | ||
| 111 | + | ### **2. INSERT 모드 출력** | |
| 112 | + | ```sql | |
| 113 | + | BEGIN; | |
| 114 | + | CREATE TABLE public.roads ( | |
| 115 | + | gid serial PRIMARY KEY, | |
| 116 | + | name varchar(254), | |
| 117 | + | geom geometry(LINESTRING,4326) | |
| 118 | + | ); | |
| 119 | + | ||
| 120 | + | INSERT INTO public.roads (name, geom) VALUES ('Main St', ST_GeomFromText('LINESTRING(-122.4 37.8, -122.5 37.9)', 4326)); | |
| 121 | + | INSERT INTO public.roads (name, geom) VALUES ('Oak Ave', ST_GeomFromText('LINESTRING(-122.3 37.7, -122.4 37.8)', 4326)); | |
| 122 | + | INSERT INTO public.roads (name, geom) VALUES ('Pine Rd', ST_GeomFromText('LINESTRING(-122.2 37.6, -122.3 37.7)', 4326)); | |
| 123 | + | -- ... 수천/수만 개의 INSERT 문 | |
| 124 | + | COMMIT; | |
| 125 | + | ``` | |
| 126 | + | ||
| 127 | + | ### **3. COPY 모드 출력** | |
| 128 | + | ```sql | |
| 129 | + | BEGIN; | |
| 130 | + | CREATE TABLE public.roads ( | |
| 131 | + | gid serial PRIMARY KEY, | |
| 132 | + | name varchar(254), | |
| 133 | + | geom geometry(LINESTRING,4326) | |
| 134 | + | ); | |
| 135 | + | ||
| 136 | + | COPY public.roads (name, geom) FROM stdin; | |
| 137 | + | Main St 0102000020E6100000020000000000000000C05EC0000000000000... | |
| 138 | + | Oak Ave 0102000020E6100000020000000000000000A05EC0000000000000... | |
| 139 | + | Pine Rd 0102000020E6100000020000000000000000805EC0000000000000... | |
| 140 | + | \. | |
| 141 | + | COMMIT; | |
| 142 | + | ``` | |
| 143 | + | ||
| 144 | + | ## ⚡ **COPY 모드의 성능 우위** | |
| 145 | + | ||
| 146 | + | ### **4. 성능 차이 이유** | |
| 147 | + | ||
| 148 | + | | 측면 | INSERT 모드 | COPY 모드 | | |
| 149 | + | |------|-------------|-----------| | |
| 150 | + | | **처리 방식** | 행별 개별 처리 | 배치 스트림 처리 | | |
| 151 | + | | **트랜잭션** | 각 INSERT마다 오버헤드 | 단일 트랜잭션 | | |
| 152 | + | | **SQL 파싱** | 각 문장마다 파싱 | 한 번만 파싱 | | |
| 153 | + | | **네트워크** | 많은 왕복 통신 | 스트림 전송 | | |
| 154 | + | | **메모리** | 높은 사용량 | 효율적 사용 | | |
| 155 | + | | **속도** | 기준 (1x) | **10-100배 빠름** | | |
| 156 | + | ||
| 157 | + | ### **5. 내부 동작 과정** | |
| 158 | + | ||
| 159 | + | ``` | |
| 160 | + | 1. SHP 파일 읽기 | |
| 161 | + | ├─ .shp (지리 정보) | |
| 162 | + | ├─ .dbf (속성 정보) | |
| 163 | + | └─ .shx (인덱스 정보) | |
| 164 | + | ||
| 165 | + | 2. 데이터 변환 | |
| 166 | + | ├─ 좌표계 변환 (필요시) | |
| 167 | + | ├─ 인코딩 변환 | |
| 168 | + | └─ PostgreSQL 형식으로 변환 | |
| 169 | + | ||
| 170 | + | 3. COPY 문장 생성 | |
| 171 | + | ├─ COPY table_name FROM stdin; | |
| 172 | + | ├─ 탭으로 구분된 데이터 스트림 | |
| 173 | + | └─ 종료 마커 (\.) | |
| 174 | + | ||
| 175 | + | 4. PostgreSQL 처리 | |
| 176 | + | ├─ 배치 단위로 메모리에 적재 | |
| 177 | + | ├─ 인덱스 업데이트 지연 | |
| 178 | + | └─ WAL 로그 최적화 | |
| 179 | + | ``` | |
| 180 | + | ||
| 181 | + | ## 💾 **메모리 및 I/O 최적화** | |
| 182 | + | ||
| 183 | + | ### **6. COPY 모드의 효율성** | |
| 184 | + | ||
| 185 | + | **INSERT 모드:** | |
| 186 | + | ```bash | |
| 187 | + | # 각 행마다 메모리 할당/해제 반복 | |
| 188 | + | PostgreSQL: INSERT 파싱 → 실행 계획 → 실행 → 해제 | |
| 189 | + | PostgreSQL: INSERT 파싱 → 실행 계획 → 실행 → 해제 | |
| 190 | + | PostgreSQL: INSERT 파싱 → 실행 계획 → 실행 → 해제 | |
| 191 | + | # ... 수만 번 반복 | |
| 192 | + | ``` | |
| 193 | + | ||
| 194 | + | **COPY 모드:** | |
| 195 | + | ```bash | |
| 196 | + | # 한 번의 설정으로 모든 데이터 처리 | |
| 197 | + | PostgreSQL: COPY 파싱 → 실행 계획 → 배치 스트림 처리 → 완료 | |
| 198 | + | ``` | |
| 199 | + | ||
| 200 | + | ### **7. 네트워크 효율성** | |
| 201 | + | ||
| 202 | + | **INSERT 모드:** | |
| 203 | + | - 수만 개의 개별 SQL 문장 전송 | |
| 204 | + | - 각 INSERT마다 응답 대기 | |
| 205 | + | - 높은 네트워크 오버헤드 | |
| 206 | + | ||
| 207 | + | **COPY 모드:** | |
| 208 | + | - 단일 COPY 명령 + 데이터 스트림 | |
| 209 | + | - 응답 대기 최소화 | |
| 210 | + | - 낮은 네트워크 오버헤드 | |
| 211 | + | ||
| 212 | + | ## 🎯 **실제 사용 시 주의사항** | |
| 213 | + | ||
| 214 | + | ### **8. COPY 모드 제한사항** | |
| 215 | + | ||
| 216 | + | ```bash | |
| 217 | + | # 장점 | |
| 218 | + | ✅ 빠른 속도 (10-100배) | |
| 219 | + | ✅ 낮은 메모리 사용량 | |
| 220 | + | ✅ 효율적인 네트워크 사용 | |
| 221 | + | ✅ 트랜잭션 오버헤드 최소화 | |
| 222 | + | ||
| 223 | + | # 주의사항 | |
| 224 | + | ⚠️ 오류 발생 시 전체 롤백 | |
| 225 | + | ⚠️ 트리거 실행 안됨 (일부 버전) | |
| 226 | + | ⚠️ 실시간 모니터링 어려움 | |
| 227 | + | ⚠️ 중간 취소 어려움 | |
| 228 | + | ``` | |
| 229 | + | ||
| 230 | + | ### **9. 대용량 파일 처리 시** | |
| 231 | + | ||
| 232 | + | **4GB SHP 파일 처리:** | |
| 233 | + | - **INSERT 모드**: 10-20시간 소요 | |
| 234 | + | - **COPY 모드**: 1-2시간 소요 | |
| 235 | + | - **메모리 사용**: COPY가 50-70% 적음 | |
| 236 | + | ||
| 237 | + | 따라서 현재 스크립트에서 `-D` 옵션을 사용하는 것은 **매우 효율적인 선택**입니다! | |
上一頁
下一頁