ATTACH 및 DETACH 문
ATTACH 및 DETACH 문
DuckDB는 데이터베이스 파일에 부착(attach)하고 분리(detach)할 수 있어요. 여러 데이터베이스 파일에 동시에 접근하거나 데이터를 옮길 때 유용하죠.
출처: 문서
본문
DuckDB는 데이터베이스 파일에 부착하고 분리하는 것을 허용해요.
예제
이름에서 유추된 별칭(file)으로 데이터베이스 file.db를 부착해요.
ATTACH 'file.db';
명시적 별칭(file_db)으로 데이터베이스 file.db를 부착해요.
ATTACH 'file.db' AS file_db;
읽기 전용 모드로 데이터베이스 file.db를 부착해요.
ATTACH 'file.db' (READ_ONLY);
블록 크기 16 kB로 데이터베이스 file.db를 부착해요.
ATTACH 'file.db' (BLOCK_SIZE 16_384);
행 그룹 크기 2048 행으로 데이터베이스 file.db를 부착해요.
ATTACH 'file.db' (ROW_GROUP_SIZE 2048);
성능 향상을 위해 WAL 쓰기를 비활성화한 채 데이터베이스 file.db를 부착해요.
ATTACH 'file.db' (RECOVERY_MODE no_wal_writes);
읽기와 쓰기를 위해 SQLite 데이터베이스를 부착해요 (자세한 내용은 sqlite 확장 참고).
ATTACH 'sqlite_file.db' AS sqlite_db (TYPE sqlite);
유추된 데이터베이스 별칭 file이 아직 없을 때만 데이터베이스 file.db를 부착해요.
ATTACH IF NOT EXISTS 'file.db';
명시적 데이터베이스 별칭 file_db가 아직 없을 때만 데이터베이스 file.db를 부착해요.
ATTACH IF NOT EXISTS 'file.db' AS file_db;
별칭 file_db로 file2.db를 부착하되, 기존 별칭이 있으면 분리하고 교체해요.
ATTACH OR REPLACE 'file2.db' AS file_db;
별칭 file로 부착된 데이터베이스에 테이블을 생성해요.
CREATE TABLE file.new_table (i INTEGER);
별칭 file로 부착된 데이터베이스를 분리해요.
DETACH file;
부착된 모든 데이터베이스 목록을 표시해요.
SHOW DATABASES;
사용할 기본 데이터베이스를 file 데이터베이스로 변경해요.
USE file;
ATTACH
ATTACH 문은 읽고 쓸 수 있는 새 데이터베이스 파일을 카탈로그에 추가해요.
부착 정의는 세션 간에 유지되지 않는다는 점에 주의해요. 새 세션 시작 시 모든 데이터베이스에 다시 부착해야 해요.
ATTACH 문법
ATTACH는 DuckDB가 여러 데이터베이스 파일에 대해 동작하게 하고, 서로 다른 데이터베이스 파일 간 데이터 전송을 허용해요.
ATTACH는 HTTP와 S3 엔드포인트를 지원해요. 이 경우 기본적으로 읽기 전용 커넥션을 생성해요. 따라서 다음 두 명령은 동일해요.
ATTACH 'https://blobs.duckdb.org/databases/stations.duckdb' AS stations_db;
ATTACH 'https://blobs.duckdb.org/databases/stations.duckdb' AS stations_db (READ_ONLY);
마찬가지로 S3에 연결하는 다음 두 명령도 동일해요.
ATTACH 's3://⟨blobs-duckdb⟩/databases/stations.duckdb' AS stations_db;
ATTACH 's3://⟨blobs-duckdb⟩/databases/stations.duckdb' AS stations_db (READ_ONLY);
명시적 저장소 버전
DuckDB v1.2.0은 STORAGE_VERSION 옵션을 도입했어요. 이를 통해 저장소 버전을 명시적으로 지정할 수 있어요. 이렇게 하면 더 새로운 전방 비호환 기능을 선택할 수 있어요.
ATTACH 'file.db' (STORAGE_VERSION 'v1.2.0');
이 설정은 데이터베이스 파일을 읽을 수 있어야 하는 최소 DuckDB 버전을 지정해요. 이 옵션으로 데이터베이스 파일을 쓰면 결과 파일은 지정한 버전보다 오래된 DuckDB 버전에서는 열 수 없어요. 지정한 버전과 그 이후의 모든 새 버전의 DuckDB에서는 읽을 수 있어요.
최신 저장소 버전으로 데이터베이스를 초기화하려면 다음을 사용해요.
ATTACH 'file.db' (STORAGE_VERSION 'latest');
자세한 내용은 "Storage" 페이지를 참고해요.
데이터베이스 암호화
DuckDB는 데이터베이스 암호화를 지원해요. 기본적으로 권장되는 GCM 모드에서 256비트 키 길이의 AES 암호화를 사용해요. 암호화는 기본 데이터베이스 파일, WAL(재작성 로그) 파일, 심지어 임시 파일까지 포함해요. 암호화된 데이터베이스에 부착하려면 ENCRYPTION_KEY와 함께 ATTACH 문을 사용해요.
ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack');
데이터를 암호화할 때 DuckDB는 내장된 mbedtls 라이브러리나 httpfs 확장의 OpenSSL 라이브러리를 사용할 수 있어요. OpenSSL 버전은 하드웨어 가속 덕분에 훨씬 빠르므로, 좋은 암호화 성능을 위해 httpfs를 로드해두는 걸 권장해요.
LOAD httpfs;
ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack'); -- will be faster thanks to httpfs
AES 모드를 CBC 또는 CTR로 변경하려면 ENCRYPTION_CIPHER 옵션을 사용해요.
ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack', ENCRYPTION_CIPHER 'CBC');
ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack', ENCRYPTION_CIPHER 'CTR');
데이터베이스 암호화는 저장소 버전 1.4.0 이상을 의미해요.
옵션
ATTACH 문 뒤 괄호 안에 0개 이상의 복사 옵션을 제공할 수 있어요. 파라미터 값은 작은따옴표로 감싸거나 감싸지 않고 전달할 수 있어요. 파라미터 값에 임의의 표현식을 사용할 수 있어요.
| 이름 | 설명 | 타입 | 기본값 |
|---|---|---|---|
READ_ONLY |
데이터베이스를 읽기 전용 모드로 부착. 읽기-쓰기 모드로 부착하려면 READ_WRITE(기본값) 사용. |
BOOLEAN |
false |
COMPRESS |
데이터베이스가 압축되었는지 여부. 메모리 내 데이터베이스에만 적용 가능. | VARCHAR |
false |
TYPE |
파일 타입 (DUCKDB 또는 SQLITE), 또는 입력 문자열 리터럴로부터 유추 (MySQL, PostgreSQL). |
VARCHAR |
DUCKDB |
DEFAULT_TABLE |
부착된 데이터베이스가 카탈로그 이름으로 직접 참조될 때(예: FROM ⟨db⟩) 쿼리되는 테이블. |
VARCHAR |
- |
BLOCK_SIZE |
새 데이터베이스 파일의 블록 크기. 2의 거듭제곱이어야 하고 [16384, 262144] 범위여야 함. 기존 파일에는 설정 불가. | UBIGINT |
262144 |
ROW_GROUP_SIZE |
새 데이터베이스 파일의 행 그룹 크기. | UBIGINT |
122880 |
STORAGE_VERSION |
사용되는 저장소 버전. | VARCHAR |
v1.0.0 |
ENCRYPTION_KEY |
데이터베이스 암호화에 사용되는 암호화 키. | VARCHAR |
- |
ENCRYPTION_CIPHER |
데이터베이스 암호화에 사용되는 암호화 알고리즘 (CBC, CTR 또는 GCM). |
VARCHAR |
- |
RECOVERY_MODE |
데이터베이스의 복구 모드. no_wal_writes는 WAL 쓰기를 비활성화해 성능을 개선하지만 크래시 복구를 희생함. |
VARCHAR |
- |
DETACH
DETACH 문은 이전에 부착된 데이터베이스 파일을 닫고 분리해, 데이터베이스 파일에 대한 잠금을 해제해요.
기본 데이터베이스에서 분리하는 것은 불가능하다는 점에 주의해요. 그렇게 하려면 USE 문으로 기본 데이터베이스를 다른 것으로 변경해요. 예를 들어 영구 데이터베이스에 연결되어 있다면 다음을 실행해 메모리 내 데이터베이스로 변경할 수 있어요.
ATTACH ':memory:' AS memory_db;
USE memory_db;
경고 커넥션을 닫아도(예: Python의
close()함수 호출) 데이터베이스 파일에 대한 잠금은 해제되지 않아요. 파일 핸들을 메인 DuckDB 인스턴스(Python의 경우duckdb모듈)가 보유하고 있기 때문이에요.
이름 한정(Name Qualification)
카탈로그 객체의 완전 한정 이름은 객체의 카탈로그, 스키마, _이름_을 포함해요. 예를 들어:
데이터베이스 new_db를 부착해요.
ATTACH 'new_db.db';
데이터베이스 new_db에 스키마 my_schema를 생성해요.
CREATE SCHEMA new_db.my_schema;
스키마 my_schema에 테이블 my_table을 생성해요.
CREATE TABLE new_db.my_schema.my_table (col INTEGER);
테이블 my_table 안의 컬럼 col을 참조해요.
SELECT new_db.my_schema.my_table.col FROM new_db.my_schema.my_table;
완전 한정 이름이 항상 필요한 것은 아니라는 점에 주의해요. 이름이 완전 한정되지 않으면 시스템은 _카탈로그 검색 경로_를 사용해 참조할 항목을 찾아요. 기본 카탈로그 검색 경로는 시스템 카탈로그, 임시 카탈로그, main 스키마와 함께 처음 부착된 데이터베이스를 포함해요.
특히 식별자와 데이터베이스 이름에 대한 규칙도 참고해요.
기본 데이터베이스와 스키마
테이블을 한정 없이 생성하면 기본 데이터베이스의 기본 스키마에 생성돼요. 기본 데이터베이스는 시스템 생성 시 시작되는 데이터베이스이고, 기본 스키마는 main이에요.
기본 데이터베이스에 테이블 my_table을 생성해요.
CREATE TABLE my_table (col INTEGER);
기본 데이터베이스와 스키마 변경
기본 데이터베이스와 스키마는 USE 명령으로 변경할 수 있어요.
기본 데이터베이스 스키마를 new_db.main으로 설정해요.
USE new_db;
기본 데이터베이스 스키마를 new_db.my_schema로 설정해요.
USE new_db.my_schema;
충돌 해결
단일 한정자만 제공할 때, 충돌이 없으면 시스템은 이를 카탈로그 또는 스키마 중 하나로 해석할 수 있어요. 예를 들어:
ATTACH 'new_db.db';
CREATE SCHEMA my_schema;
테이블 new_db.main.tbl을 생성해요.
CREATE TABLE new_db.tbl (i INTEGER);
테이블 default_db.my_schema.tbl을 생성해요.
CREATE TABLE my_schema.tbl (i INTEGER);
충돌(같은 이름의 스키마와 카탈로그가 모두 존재)을 만들면 시스템은 완전 한정 경로를 사용할 것을 요청해요.
CREATE SCHEMA new_db;
CREATE TABLE new_db.tbl (i INTEGER);
Binder Error:
Ambiguous reference to catalog or schema "new_db" - use a fully qualified path like "memory.new_db"
카탈로그 검색 경로 변경
카탈로그 검색 경로는 search_path 구성 옵션을 설정해 조정할 수 있어요. 검색 경로에 포함될 쉼표로 구분된 값 목록을 사용해요. 다음 예제는 두 데이터베이스에서 검색하는 방법을 보여줘요.
ATTACH ':memory:' AS db1;
ATTACH ':memory:' AS db2;
CREATE table db1.tbl1 (i INTEGER);
CREATE table db2.tbl2 (j INTEGER);
완전 한정 이름으로 테이블을 참조해요.
SELECT * FROM db1.tbl1;
SELECT * FROM db2.tbl2;
또는 검색 경로를 설정하고 이름으로 테이블을 참조해요.
SET search_path = 'db1,db2';
SELECT * FROM tbl1;
SELECT * FROM tbl2;
트랜잭션 시맨틱
여러 데이터베이스에서 쿼리를 실행할 때 시스템은 데이터베이스마다 별도의 트랜잭션을 엽니다. 트랜잭션은 기본적으로 lazily 시작돼요. 주어진 데이터베이스가 쿼리에서 처음 참조될 때 그 데이터베이스에 대한 트랜잭션이 시작돼요. SET immediate_transaction_mode = true를 설정하면 대신 모든 부착된 데이터베이스에서 트랜잭션을 즉시 시작하도록 동작을 변경할 수 있어요.
여러 트랜잭션이 동시에 활성화될 수 있지만, 시스템은 단일 트랜잭션에서 하나의 부착된 데이터베이스에만 _쓰기_를 지원해요. 단일 트랜잭션에서 여러 부착된 데이터베이스에 쓰려고 하면 다음 오류가 발생해요.
Attempting to write to database "db2" in a transaction that has already modified database "db1" -
a single transaction can only write to a single attached database.
이 제한의 이유는 시스템이 부착된 데이터베이스 간 트랜잭션의 원자성을 유지하지 않기 때문이에요. 트랜잭션은 각 데이터베이스 파일 _내_에서만 원자적이에요. 전역 트랜잭션이 단일 데이터베이스 파일에만 쓰도록 제한함으로써 원자성 보장을 유지해요.
더 알아보기 (Learn more)
- USE 문에서 기본 데이터베이스 변경 방법을 확인해요.
- Storage 문서에서 저장소 버전을 더 자세히 살펴볼 수 있어요.