Part I. Tutorial

목차

1. 시작하기
1.1. 설치
1.2. 아키텍 기초
1.3. 데이터베이스 생성
1.4. 데이터베이스에 액세스
2. SQL 언어
2.1. 소개
2.2. 개념
2.3. 새 테이블 만들기
2.4. 행으로 테이블 채우기
2.5. 테이블 쿼리
2.6. 테이블 간 조인
2.7. 집계 함수
2.8. 업데이트
2.9. 삭제
3. 고급 기능
3.1. 소개
3.2. 뷰
3.3. 외래 키
3.4. 트랜잭션
3.5. Window 함수
3.6. 계층
3.7. 결론 

 

1. 시작하기

1.1. 아키텍처

 PostgreSQL은 클라이언트/서버 모델을 사용합니다. PostgreSQL 세션 은 다음과 같은 프로세스(프로그램)로 구성됩니다.

  • 데이터베이스 서버 프로그램  : 데이터베이스 파일을 관리하는 서버 프로세스는 클라이언트의 연결을 수락하고 데이터베이스 작업을 수행합니다. 
  • 데이터베이스 작업을 수행하려는 사용자의 클라이언트(프런트엔드) 애플리케이션 : 클라이언트는 텍스트 도구, 그래픽 애플리케이션, 웹 페이지를 표시하기 위해 데이터베이스에 액세스하는 웹 서버 또는 데이터베이스 유지.관리 도구입니다.

일반적인 클라이언트/서버 응용 프로그램과 마찬가지로 클라이언트와 서버는 TCP/IP 네트워크 연결을 통해 통신합니다. 

PostgreSQL 서버 는 클라이언트의 여러 동시 연결을 처리할 수 있습니다. 이를 위해 각 연결에 대해 새로운 프로세스를 시작( "fork" )합니다. 그 시점부터 클라이언트와 fork된 서버 프로세스는 원래 postgres프로세스의 개입 없이 통신합니다.

1.2. 설치

https://www.postgresql.org/download/ 에서 설치 환경(OS, Windows, MacOS, Linux, Solaris 등) 에 맞는 설치파일을 다운로드 한 후 설치한다.

윈도우에 설치 시 아래 4개 컴포넌트가 설치된다.

  • PostgreSQL Server : PostgreSQL Database Server
  • pgAdmin : PostgreSQL database 관리와 작업을 위한 GUI 툴
  • Stack Builder : 추가 툴이나 driver 그리고 Application 등을 다운로드를 위한 
  • Command Line Tools : DB접속을 위한 Cli 툴

윈도우에 설치 시 superuser(posgres)에 대한 패스워드, DB Port, Locale 입력화면이 나오면 원하는 값 입력한다. 

Linux나 MacOS 에 설치는 https://www.postgresql.org/download  페이지를 참고한다.

1.3. DB 접속

1) psql 로 접속

Database가 설치된 서버에서 접속 시에는 host를 생략할 수 있고, default port를 사용하는 경우에는 port 생략 가능

$ psql -h {host} -p {port} -U {user} -d {database}

2) SQL Shell을 이용한 접속

Windows 에 설치된 "SQL Shell(psql)" 을 실행시킨 후 DB 접속을 위한 정보를 차례로 입력한다.

 

3) client 툴로 접속

클라이언트 툴(TablePlus, Psequel, PgAdmin, Postico, Azure Data Studio, DBeaver, Command Line Tool 등)을 이용하여 DB에 접속한다. 본 문서에서는 TablePlus로 접속하는 방법을 설명한다.

 

- TablePlus 실행 화면에서 마우스 오른쪽 버튼을 클릭한 다음 "[New] - PostgreSQL" 선택한다

 

- 아래와 같이 DB 접속을 위한 화면에 DB 정보를 입력한다.

-

  • Name : 임의의 별칭(Alias) 입력
  • Host : DB서버의 IP나 hostname, endpoint 등을 입력. 본 문서에서는 PC에 설치했으므로 localhost 입력
  • Port : 설치 시 입력했던 Port 입력(Default Port는 5432)
  • User : postgress 입력
  • Password : 설치 시 입력했던 password 입력
  • Database : 기본적으로 postgres database 가 설치되므로 postgresql을 입력해도 되고 공란으로 유지해 된다.

입력이 완료되면 [Test] 를 수행한 후 정상 접속이 확인되면 [Save] 버튼을 클릭하여 저장한다.

 

4) java, python 등의 프로그램으로 접속

 

1.3. 데이터베이스 생성

mydb 데이터베이스 생성:

CREATE DATABASE mydb;

 

 

salesspace 테이블스페이스를 사용하여 사용자 salesapp이 소유한 데이터베이스 sales 생성

CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace;

 

1.4. 도메인 생성

postgreSQL의 자료형에는 Domain Types이 있습니.

도메인은 선택적 제약 조건(허용되는 값 집합에 대한 제한 사항)이 있는 데이터 유형입니다. 도메인을 정의하는 사용자가 도메인의 소유자가 됩니다. 

 

DOMAIN 생성 문법

CREATE DOMAIN name [ AS ] data_type
    [ COLLATE collation ]
    [ DEFAULT expression ]
    [ constraint [ ... ] ]

where constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | CHECK (expression) }
  • name: 사용자 정의 데이터 유형의 이름
  • data_type: 데이터 유형
  • COLLATE : 도메인에 대한 데이터 정렬입니다. 데이터 정렬이 지정되지 않은 경우 도메인은 기본 데이터 유형과 동일한 데이터 정렬 동작을 합니다. 
  • DEFAULT default_value: 기본값 (선택 사항)
  • CONSTRAINT constraint_name: 제약 조건의 이름 (선택 사항)
  • NOT NULL: NULL 값을 허용하지 않음 (선택 사항)
  • CHECK (expression): 값 유효성 검사를 위한 표현식 (선택 사항)

Domain Examples

이 예에서는 us_postal_code 데이터 유형을 생성한 다음 테이블 정의에 해당 유형을 사용합니다. 정규식 테스트는 값이 유효한 미국 우편번호인지 확인하는 데 사용됩니다. 아래 도메인 제약은 5자리 정수 입력 허용과 5자리-4자리 정수 입력만을 허용하는 규칙입니다.

CREATE DOMAIN us_postal_code AS TEXT
CHECK(
   VALUE ~ '^\d{5}$'
OR VALUE ~ '^\d{5}-\d{4}$'
);

CREATE TABLE us_snail_addy (
  address_id SERIAL PRIMARY KEY,
  city TEXT NOT NULL,
  postal us_postal_code NOT NULL
);

 

INSERT INTO us_snail_addy(city, postal) VALUES('LOS ANGELES', '12345-1234');  /* 입력성공 */
INSERT INTO us_snail_addy(city, postal) VALUES('LOS ANGELES', '12345-12345'); /* 입력실패 */

INSERT INTO us_snail_addy(city, postal) VALUES('LOS ANGELES', 'a2345-1234'); /* 입력실패 */

 

현재 접속한 Database 확인

현재 접속한 데이터베이스를 확인한다.

SELECT CURRENT_DATABASE();

 

현재 접속한 User 확인

현재 접속한 user 를 확인한다.

SELECT CURRENT_USER;

 

1.5. 스키마(Schema) 생성

CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ]
CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ]
CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ]
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification

where role_specification can be:

    user_name
  | CURRENT_ROLE
  | CURRENT_USER
  | SESSION_USER

현재 데이터베이스에 새 스키마를 생성합니다.

스키마 이름은 현재 데이터베이스에 있는 기존 스키마의 이름과 달라야 합니다.

스키마는 본질적으로 네임스페이스입니다. 

AUTHORIZATION절이 사용되는 경우 생성된 모든 객체가 해당 사용자의 소유라는 점을 제외하면 스키마를 생성한 후 실행되는 별도의 명령과 기본적으로 동일하게 처리됩니다 .

--  스키마 경로 설정
set search_path To postgres, public;

 

위와 같은 설정에서 테이블 명칭만 입력하면 DBMS 가 해당 테이블을 찾을 때
postgres ➔ public 순으로 찾게 됩니다.

 

PostgreSQL에서는 모든 연결이 하나의 데이터베이스에서만 작동합니다. 따라서 데이터베이스를 변경하려면 다른 데이터베이스를 지정하여 다시 연결해야 합니다. MySQL 에 존재하는 'use dbname' 명령어가 없습니다.

 

 

1.6. 계정(User) 생성

CREATE USER name [ [ WITH ] option [ ... ] ]

where option can be:
    
      SYSID uid 
    | CREATEDB | NOCREATEDB
    | CREATEUSER | NOCREATEUSER
    | IN GROUP groupname [, ...]
    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password'
    | VALID UNTIL 'abstime'

 

name : 계정명

SYSID : SYSID 절을 사용하여 새 사용자의 PostgreSQL 사용자 ID를 선택할 수 있습니다. 일반적으로 필요하지 않지만 고아 개체( orphaned object)의 소유자를 다시 만들어야 하는 경우 유용할 수 있습니다.
이를 지정하지 않으면 할당된 가장 높은 사용자 ID에 1을 더한 값(최소 100)이 기본값으로 사용됩니다.

CREATEDB | NOCREATEDB : 

데이터베이스 생성 권한을 정의합니다. default는 NOCREATEDB입니다.

 

CREATEUSER | NOCREATEUSER

데이터베이스 생성 권한을 정의합니다. default는 NOCREATEUSER 입니다.

 

IN GROUP groupname

사용자의 그룹 이름입니다. 여러 그룹 이름이 나열될 수 있습니다.

 

PASSWORD

사용자의 비밀번호를 설정합니다. 비밀번호 인증을 사용할 계획이 없다면 이 옵션을 생략할 수 있지만, 비밀번호 인증으로 전환하기로 결정하면 사용자는 연결할 수 없습니다. 비밀번호는 나중에 ALTER USER를 사용하여 설정하거나 변경할 수 있습니다.

 

ENCRYPTED | UNENCRYPTED

비밀번호가 시스템 카탈로그에 암호화되어 저장되는지 여부를 제어합니다. (두 가지 모두 지정되지 않은 경우 매개변수 password_encryption에 의해 결정됩니다.) 제시된 비밀번호 문자열이 이미 MD5 암호화 형식인 경우 ENCRYPTED 또는 UNENCRYPTED가 지정되었는지 여부에 관계없이 있는 그대로 암호화되어 저장됩니다. 시스템은 지정된 암호화된 비밀번호 문자열을 해독할 수 없습니다). 이를 통해 덤프/복원 중에 암호화된 비밀번호를 다시 로드할 수 있습니다.

 

VALID UNTIL : 비밀번호가 더 이상 유효하지 않게 되는 시간을 설정합니다. 생략하면 비밀번호는 항상 유효합니다.

 

--Create User

CREATE USER my_user_test WITH LOGIN NOSUPERUSER NOCREATEDB  NOCREATEROLE    INHERIT NOREPLICATION   CONNECTION LIMIT -1 PASSWORD 'xxxxxxx';

-- Grant connect to my data base

GRANT CONNECT ON DATABASE my_db_test TO my_user_test;

-- Grant usage the schema

GRANT USAGE ON SCHEMA my_sch_test TO my_user_test ;

-- Grant all table for SELECT, INSERT, UPDATE, DELETE

GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA my_sch_test TO my_user_test;

 

 

1.7. 권한 부여

schema에 읽기 권한 주기

GRANT USAGE ON SCHEMA public TO <계정명>;

 

schema의 모든 table에 읽기 권한 주기

GRANT SELECT ON ALL TABLES IN SCHEMA schema_name TO username;

 

 

 

 

2. SQL 언어

 

2.1. 소개

 

2.2. 개념

 

2.3. 새 테이블 만들기

 

2.4. 행으로 테이블 채우기

 

2.5. 테이블 쿼리

 

2.6. 테이블 간 조인

 

2.7. 집계 함수

 

2.8. 업데이트

 

2.9. 삭제

 

3. 고급 기능

 

3.1. 소개

 

3.2. 뷰

 

3.3. 외래 키

 

3.4. 트랜잭션

 

3.5. Window 함수

 

3.6. 계층

 

3.7. 결론 

 

 

 

 

 

 

 

1. Multi-Primary and Single-Primary Modes

 

그룹 복제는 단일 기본 모드 또는 다중 기본 모드에서 작동합니다. 그룹 모드는 group_replication_single_primary_mode 시스템 변수로 지정되는 그룹 전체 구성 설정이며 모든 구성원이 동일해야 합니다. "ON" 설정은 기본 모드인 단일 기본 모드를 의미하며, "OFF" 설정은 다중 기본 모드를 의미합니다. 그룹의 구성원을 서로 다른 모드로 배포하는 것은 불가능합니다. 예를 들어 한 구성원은 다중 기본 모드로 구성되고 다른 구성원은 단일 기본 모드로 구성하는 것은 불가능합니다.

그룹 복제가 실행되는 동안에는 group_replication_single_primary_mode  값을 수동으로 변경할 수 없습니다 . MySQL 8.0.13부터 group_replication_switch_to_single_primary_mode()  group_replication_switch_to_multi_primary_mode() 기능을 사용하여 그룹 복제가 계속 실행되는 동안 그룹을 한 모드에서 다른 모드로 이동할 수 있습니다. 이러한 기능은 그룹 모드 변경 프로세스를 관리하고 데이터의 안전과 일관성을 보장합니다. 이전 릴리스에서는 그룹 모드를 변경하려면 그룹 복제를 중지하고 group_replication_single_primary_mode 모든 구성원의 값을 변경해야 합니다. 그런 다음 그룹의 전체 재부팅(를 사용하는 서버의 부트스트랩 group_replication_bootstrap_group=ON)을 수행하여 새 운영 구성에 대한 변경 사항을 구현합니다. 

 

1.1 Single-Primary Mode

단일 기본 모드( group_replication_single_primary_mode=ON)에서 그룹에는 읽기-쓰기 모드로 설정된 단일 기본 서버가 있습니다. 그룹의 다른 모든 구성원은 읽기 전용 모드로 설정됩니다( 사용 super_read_only=ON). 기본 서버는 일반적으로 그룹을 부트스트랩하는 첫 번째 서버입니다. 그룹에 참여하는 다른 모든 서버는 기본 서버에 대해 학습하고 자동으로 읽기 전용 모드로 설정됩니다.

단일 기본 모드에서 그룹 복제는 단일 서버만 그룹에 쓰도록 강제하므로 다중 기본 모드에 비해 일관성 검사가 덜 엄격할 수 있으며 DDL 문을 특별히 주의해서 처리할 필요가 없습니다. 이 옵션은 group_replication_enforce_update_everywhere_checks 그룹에 대한 엄격한 일관성 검사를 활성화하거나 비활성화합니다. 단일 기본 모드로 배포하거나 그룹을 단일 기본 모드로 변경하는 경우 이 시스템 변수를 로 설정해야 합니다 OFF.

기본 서버로 지정된 구성원은 다음과 같은 방법으로 변경할 수 있습니다.

  • 자발적으로든 예기치 않게든 기존 기본 구성원이 그룹을 떠나면 새 기본 구성원이 자동으로 선출됩니다.
  • 기능 을 사용하여 특정 구성원을 새로운 기본 구성원으로 지정할 수 있습니다 group_replication_set_as_primary() .
  • 이 기능을 사용하여 group_replication_switch_to_single_primary_mode() 다중 기본 모드에서 실행 중인 그룹을 단일 기본 모드로 실행하도록 변경하면 새 기본이 자동으로 선택되거나 기능으로 지정하여 새 기본을 지정할 수 있습니다.

이 기능은 모든 그룹 구성원이 MySQL 8.0.13 이상을 실행하는 경우에만 사용할 수 있습니다. 새로운 기본 서버가 자동으로 선택되거나 수동으로 지정되면 자동으로 읽기-쓰기로 설정되고 다른 그룹 구성원은 보조 서버로 유지되므로 읽기 전용입니다. 그림 20.4, “새 예비선거”는 이 과정을 보여줍니다.

그림 20.4 새로운 예비선거

새로운 기본 서버가 선택되거나 임명되면 이전 기본 서버에는 적용되었지만 아직 이 서버에는 적용되지 않은 변경 사항의 백로그가 있을 수 있습니다. 이 상황에서는 새 기본이 이전 기본을 따라잡을 때까지 읽기-쓰기 트랜잭션이 충돌을 일으키고 롤백될 수 있으며 읽기 전용 트랜잭션으로 인해 오래된 읽기가 발생할 수 있습니다. 빠른 구성원과 느린 구성원 간의 차이를 최소화하는 그룹 복제의 흐름 제어 메커니즘은 활성화되고 적절하게 조정되면 이러한 일이 발생할 가능성을 줄입니다. 흐름 제어에 대한 자세한 내용은 20.7.2절 “흐름 제어”를 참조하십시오 . MySQL 8.0.14부터는 group_replication_consistency 시스템 변수를 사용하여 그룹의 트랜잭션 일관성 수준을 구성하여 이 문제를 방지할 수도 있습니다. 설정 BEFORE_ON_PRIMARY_FAILOVER(또는 더 높은 일관성 수준)은 백로그가 적용될 때까지 새로 선택된 기본에서 새 트랜잭션을 유지합니다. 트랜잭션 일관성에 대한 자세한 내용은 섹션 20.5.3, “트랜잭션 일관성 보장”을 참조하십시오 . 흐름 제어 및 트랜잭션 일관성 보장이 그룹에 사용되지 않는 경우 클라이언트 애플리케이션을 다시 라우팅하기 전에 새 기본이 복제 관련 릴레이 로그를 적용할 때까지 기다리는 것이 좋습니다.

20.1.3.1.1 예비선거 알고리즘

자동 기본 구성원 선택 프로세스에는 각 구성원이 그룹의 새로운 관점을 살펴보고, 잠재적인 새 기본 구성원을 주문하고, 가장 적합한 구성원을 선택하는 과정이 포함됩니다. 각 구성원은 MySQL Server 릴리스의 기본 선택 알고리즘에 따라 로컬에서 자체 결정을 내립니다. 모든 구성원은 동일한 결정에 도달해야 하기 때문에 다른 그룹 구성원이 더 낮은 MySQL Server 버전을 실행하는 경우 구성원은 기본 선택 알고리즘을 조정하여 그룹에서 가장 낮은 MySQL Server 버전을 가진 구성원과 동일한 동작을 하게 됩니다.

예비선거를 선출할 때 회원들이 고려하는 요소는 순서대로 다음과 같습니다.

  1. 고려되는 첫 번째 요소는 어떤 멤버가 가장 낮은 MySQL Server 버전을 실행하고 있는지입니다. 모든 그룹 구성원이 MySQL 8.0.17 이상을 실행하는 경우 구성원은 먼저 릴리스의 패치 버전을 기준으로 정렬됩니다. 멤버가 MySQL Server 5.7 또는 MySQL 8.0.16 이하를 실행 중인 경우 멤버는 먼저 릴리스의 주요 버전을 기준으로 정렬되고 패치 버전은 무시됩니다.
  2. 두 명 이상의 멤버가 가장 낮은 MySQL Server 버전을 실행하는 경우 고려되는 두 번째 요소는 group_replication_member_weight 멤버의 시스템 변수에 지정된 각 멤버의 멤버 가중치입니다. 그룹의 멤버 중 하나라도 이 시스템 변수를 사용할 수 없는 MySQL Server 5.7을 실행 중인 경우 이 요소는 무시됩니다.
  3. 시스템 group_replication_member_weight 변수는 0-100 범위의 숫자를 지정합니다. 모든 구성원의 기본 가중치는 50이므로 순서를 낮추려면 이보다 낮은 가중치를 설정하고 순서를 높이려면 그보다 높은 가중치를 설정합니다. 이 가중치 기능을 사용하면 더 나은 하드웨어 사용의 우선순위를 지정하거나 기본의 예약된 유지 관리 중에 특정 멤버에 대한 장애 조치를 보장할 수 있습니다.
  4. 둘 이상의 멤버가 가장 낮은 MySQL Server 버전을 실행하고 있고 해당 멤버 중 둘 이상이 가장 높은 멤버 가중치를 갖는 경우(또는 멤버 가중치가 무시되는 경우) 고려되는 세 번째 요소는 각 멤버의 생성된 서버 UUID의 사전순입니다. , 시스템 변수에 지정된 대로 server_uuid. 서버 UUID가 가장 낮은 멤버가 기본 멤버로 선택됩니다. 이 요소는 중요한 요소에 의해 결정될 수 없는 경우 모든 그룹 구성원이 동일한 결정에 도달할 수 있도록 보장되고 예측 가능한 결정의 역할을 합니다.
20.1.3.1.2 기본 찾기

단일 기본 모드로 배포된 경우 현재 기본 서버인 서버를 확인하려면 MEMBER_ROLE표의 열을 사용하세요 performance_schema.replication_group_members . 예를 들어:

mysql> SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
+-------------------------+-------------+
| MEMBER_HOST             | MEMBER_ROLE |
+-------------------------+-------------+
| remote1.example.com     | PRIMARY     |
| remote2.example.com     | SECONDARY   |
| remote3.example.com     | SECONDARY   |
+-------------------------+-------------+
경고

상태 group_replication_primary_member 변수는 더 이상 사용되지 않으며 향후 버전에서 제거될 예정입니다.

또는 group_replication_primary_member 상태 변수를 사용하십시오.

 
mysql> SHOW STATUS LIKE 'group_replication_primary_member'

 

 

explain()

 

 

Efficient Query & Covered Query

 

Covered Query

인덱스만을 사용하여 데이터를 조회할 때 Covered Query라고 한다.

예를 들어 customers collection에 name field에 인덱스를 생성한 경우,

db.customers.find({name:"홍길동"}, {_id: 0, name: 1}) 이렇게 조회한 경우에 인덱스만을 사용하여 원하는 데이터를 조회한다. 이를 Covered Query라고 한다.

 

 

MongoDB - indexes 사용법

쿼리 속도를 향상시키기 위해  인덱스를 사용한다. 인덱스는 find, update, delete 속도를 향상시킬 수 있다.

 

인덱스가 없을 경우 원하는 데이터를 찾기 위해서 Document 전체 데이터를 탐색해야 한다.

인덱스 유형

 

인덱스 사용 및 최적화

 

Explain 

Explain 명령은 다음 명령 실행에 대한 정보를 제공합니다.

: aggregate, count, distinct, find, findAndModify, delete, mapReduce, and update.

 

사용예시)

db.contacts.explain().find(find({"dob.age": {$gt : 60}})

db.contacts.explain("executionStats").find({"dob.age": {$gt : 60}})

 

참고자료

https://www.mongodb.com/docs/manual/reference/command/explain/

 

Create Index

db.contacts.createIndex({dob.age: 1}, { name: "<indexName>" } )

--> -1 인 경우 descending 인덱스 , 1 이면 ascending 인덱스

 

 

Create Compound Index

db.contacts.createIndex({dob.age: 1, gender: 1}, { name: "<indexName>" } )

 

Create Unique Index

db.contacts.createIndex({email: 1}, {inique: true}, name"<indexName>" } )

Using Index for Sorting

Partial Filters

Partial Index를 만들기 위해서는
db.collection.createIndex()메소드를 사용한 후, partialFilterExpression을 옵션을 사용한다.

이 경우 partialFilterExpression에 해당하는 데이터를 조회할 경우에만 인덱스를 사용한다.

partialFilterExpression 를 사용하는 이유는 인덱스 크기가 현저히 작아진다.

 

db.contacts.createIndex({dob.age: 1}, {partialFilterExpression: {"gender": "male"}}, name"<indexName>" } )

 

db.contacts.find({"dob.age": {$gt: 60}, gender: "male"}) 이렇게 사용해야 위에서 생성한 인덱스를 사용한다.

 

TTL(Time-To-Live) Index

db.sessions.createIndex({createdAt: 1}, {expireAfterSeconds: 10})

10초 후에 인덱스 및 데이터를 삭제한다. 일반 RDBMS에서 제공하는 temporary table 처럼 사용할 수 있다.

 

Drop Index

db.document.dropIndex(<index_name>) 또는 db.document.dropIndex(<field: 1>) 

  • db.pets.dropIndex( "catIdx" ) : 인덱스 이름으로 인덱스 삭제
  • db.pets.dropIndex( { "cat" : -1 } ) : fiedl 이름으로 인덱스 삭제

 

 

Compass는 MongoDB 데이터를 쿼리 및 분석할 수 있는 GUI 도구입니다.

 

 

Compass 다운로드 및 설치

https://www.mongodb.com/try/download/compass 에 접속하여 원하는 OS 환경의 소프트웨어를 다운로드 합니다.

본 문서에서는 Window10 에 msi 버전을 다운로드하여 설치하였습니다.

또는 아래 화면처럼 MongoDB 설치 시 나타나는 창에서 "Install MongoDB Compass"를 선택해서 설치할 수도 있습니다.

 

 

별다른 설정없이 바로 설치가 되고 프로그램이 수행됩니다.

 

 

MongoDB에 연결

PC에 MongoDB가 설치되어 있다면 DB 접속 URI 를 mongodb://localhost:27017 로 설정한 후 [Connect] 버튼을 클릭하면 MongoDB 에 접속됩니다.

MongoDB에 다른 데이터베이스를 생성하지 않았다면 기본적으로 admin, config, local 3개의 데이터베이스가 보입니다.

 

원격의 DB에 접속할 경우 

  • MongoDB의 경우: mongodb://host:port/database. 호스트는 호스트 이름, IP 주소 또는 UNIX 도메인 소켓일 수 있습니다. 연결 문자열이 포트를 지정하지 않는 경우 기본 MongoDB 포트인 27017을 사용합니다.
  • MongoDB Atlas의 경우: mongodb+srv://server.example.com/database. 호스트는 DNS SRV 레코드에 해당하는 호스트 이름일 수 있습니다. SRV 형식에는 포트가 필요하지 않으며 기본 MongoDB 포트인 27017을 사용합니다.

Database 생성

 

"Databases" 메뉴의 우측 "+" 기호를 클릭한 후 아래와 같은 화면에서 "Database Name"과 "Collection Name"을 입력한 후 [Create Database] 버튼을 클릭하여 데이터베이스와 Collection을 생성합니다.

 

데이터 입력

아래와 같은 화면에서 [ADD DATA] - Insert document 메뉴를 클릭합니다.

 

"Insert Docuement" 화면에 JSON 형식으로 key: value 형태로 값을 입력한 후 [Insert] 버튼을 클릭합니다.

JSON 형식과 테이블 형식으로 데이터를 입력할 수 있습니다.

"_id" 필드는 MongoDB에서 자동으로 입력하는 Primary Key 이며, 데이터타입은 ObjectId 타입입니다.

 

입력 시 ordered 옵션을 사용할 수 있습니다. 기본값은 true 입니다. insertMany로 여러 데이터 입력 시 ordered 가 true인 경우 처음 오류를 만나는 시점에서 입력을 중지합니다. 기존 데이터는 rollback하지 않습니다. 즉 순차적으로 입력합니다.

반면, ordered가 false인 경우 병렬로 데이터를 입력합니다. 그래서, 중복 오류가 발생하는 데이터를 제외하고 모두 입력됩니다.

 

JSON 형식 데이터 입력

 

TABLE 형식 데이터 입력

조회조건 입력

화면의 Filter 입력란에 { field: value} 형식으로 입력한 후 [Find] 버튼을 클릭하여 조회합니다.

 

Document 수정

Document 오른쪽의 연필 모양의 아이콘(Edit)을 클릭한 후, 수정하고자 하는 데이터를 수정하고, [UPDATE] 버튼을 클릭합니다. 예제에서는 홍길동을 신홍길동이라는 이름으로 변경하였습니다.

 

 

Document 삭제

Document 오른쪽의 휴지통 모양의 아이콘(Delete)을 클릭하여 Document를 삭제합니다.

 

전체 Document 수정 및 삭제

전체 document 수정 및 삭제는 아래의 버튼으로 수행합니다.

 

EXPORT DATA

- 한글 깨짐 : notepad로 연 후 다른 이름으로 저장 시 인코딩 형식을 UTF-8(BOM)으로 저장한 후 엑셀로 다시 엽니다. 또는 notepad ++ 을 사용할 경우 Encoding 메뉴에서 UTF-8 BOM을 선택한 후 저장하면 됩니다.

 

IMPORT DATA

- JSON or CSV file

 

 

 

<ObjectId의 구조>

 

ObjectId는 3개의 영역으로 나뉘어져 있다

  • 첫번째 4byte는 Unix epoch 이후 초 단위로 측정된 ObjectId의 생성을 나타내는 4바이트 타임스탬프 값
  • 두번째 5byte는 프로세스당 한 번 생성 되는 5바이트 임의 값이며 이 임의 값은 기계와 프로세스에 고유
  • 세번째 3byte는 임의의 값으로 초기화 되는 3바이트 증분 카운터

 

 

 

MongoDB에 생성

blog 데이터베이스 생성, users, posts collection 생성

> use blog

blog> db.users.insertMany([{name:"First",age:20,email:"first@a.com"}, {name:"Second",age:21,email:"second@a.com"}])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('65e803f125d99817df294c64'),
    '1': ObjectId('65e803f125d99817df294c65')
  }
}

blog> db.users.find()
[
  {
    _id: ObjectId('65e803f125d99817df294c64'),
    name: 'First',
    age: 20,
    email: 'first@a.com'
  },
  {
    _id: ObjectId('65e803f125d99817df294c65'),
    name: 'Second',
    age: 21,
    email: 'second@a.com'
  }
]

blog> db.posts.insertOne({title:"My first Post", text:"Thist is my first post", tags:["new", "tech"], creator:ObjectId('65e803f125d99817df294c65'), comments:[{text:"I like this post",author:ObjectId('65e803f125d99817df294c64')}]})
{
  acknowledged: true,
  insertedId: ObjectId('65e804b225d99817df294c66')
}

blog> db.posts.find()
[
  {
    _id: ObjectId('65e804b225d99817df294c66'),
    title: 'My first Post',
    text: 'Thist is my first post',
    tags: [ 'new', 'tech' ],
    creator: ObjectId('65e803f125d99817df294c65'),
    comments: [
      {
        text: 'I like this post',
        author: ObjectId('65e803f125d99817df294c64')
      }

 

Schema Validation

 

db.createCollection('posts',
{ 
    validator: { 
        $jsonSchema: { 
            bsonType: 'object', 
            required: ['title', 'text', 'creator', 'comments'], 
            properties: {
                titile: {
                    bsonType: "string",
                    description: "must be a string and required"
                },
                text: {
                    bsonType: "string",
                    description: "must be a string and required"
                },
                creator: {
                    bsonType: "objectId",
                    description: "must be a objectid and required"
                },
                comment: {
                    bsonType: "array",
                    description: "must be a array and required",
                    items: {
                        bsonType: "object",
                        required: ["text", "author"],
                        properties: {
                            text: {
                                bsonType: "string",
                                description: "must be a array and required"
                            },
                            author: {
                                bsonType: "objectId",
                                description: "must be a array and required"
                            }
                        }
                    }
                }
            }
        }
    }
});

 

데이터 모델리 시 고려해야 할 사항

- 데이터 페치 형식

- 얼마나 자주 데이터가 페치/변경되는지

-  데이터 저장 건수

- 데이터 연관성

- 데이터 중복 허용

- 데이터와 저장공간 한계

 

 

Useful Resources & Links

Helpful Articles/ Docs:

 

Oracle 데이터베이스에 연결하기 위한 환경 변수에는 두 가지가 있습니다. 그 중 하나는 ORACLE_SID 이고 다른 하나는  TWO_TASK 입니다.  

ORACLE_SID 는 동일한 호스트에 설치된 데이터베이스를 연결하는 데 사용되고,

TWO_TASK 는 다른 호스트에 설치된 oracle 데이터베이스를 연결하는데 사용됩니다.

 

TWO_TASK (또는 Windows의 LOCAL )는 원격 Oracle 서비스를 지정하는 데 사용되는 환경 변수입니다. 서비스 이름( tnsnames.ora 항목)을 지정하지 않고 SQL*Net 을 통해 원격 데이터베이스에 연결됩니다 . 프로그램에는 로컬 데이터베이스에 연결되어 있는 것처럼 보이지만 실제로는 원격 데이터베이스로 라우팅됩니다.

이 환경 변수는 Windows의 LOCAL 레지스트리 항목과 동일합니다 . ORACLE_SID 와 TWO_TASK 또는 LOCAL이 모두 정의된 경우 TWO_TASK 또는 LOCAL이 우선합니다.

TWO_TASK 사용법

윈도우 환경변수 설정 :

set LOCAL=oraservice1

 

유닉스/리눅스  환경변수 설정 :

$ export TWO_TASK=oraservice1
또는
$ setenv TWO_TASK oraservice1

 

여기서 'oraservice1'은 로컬 TNSNAMES.ORA 파일에 정의되어 있습니다.

일반적으로는 TNSNAMES.ORA 파일에 정의된 서비스 이름(연결 문자열)을 지정하여 원격 데이터베이스에 연결합니다.

아래 예제에서 'connect_str' 은 TNSNAMES.ORA 파일에 정의된 서비스 이름입니다.

$ sqlplus scott/tiger@connect_str

그러나, TWO_TASK를 설정하면 연결 문자열을 생략할 수 있습니다.

$ TWO_TASK=connect_str; export TWO_TASK
$ sqlplus scott/tiger

 

Multi-Tenant 로 설치된 Oracle DB 에서 "sqlplus / as sysdba" 로 기본적으로 접속하면 local DB로 접속하게 됩니다. 물론 TWO_TASK 환경변수에 영향을 받습니다. 아무것도 설정이 되어 있지 않을 경우에는 local CDB로 접속되지만 다른 설정값이 있는 경우 설정된 값의 DB로 접속됩니다.

 

아래 화면은 TWO_TASK 가 설정되어 있지 않은 DB 서버에서 명령어를 수행한 화면입니다. Local DB 에 접속되는 것을 

 

PDB 접속 방법

DB 서버 외부에서 접속할때는 어차피 다 SQL*Net 이나 JDBC 형태로 접속하기 때문에 싱글DB에 접속하는 것과 방법은 똑같습니다.

DB 서버 내부에서 SQL*Plus 로 접속하는 경우는 아래와 같이 4가지 방식을 사용할 수 있습니다.

 

1) CDB 에 접속한 후 alter session 커맨드로 세션 변경

2) tnsnames.ora 파일 세팅후 @TNS 로 접속

3) Easy Connect 방식으로 접속

4) TWO_TASK 설정해서 접속

 

 

1) CDB 에 접속한 후 alter session 커맨드로 세션 변경

sqlplus / as sysdba 로 CDB 에 접속한 후에, "alter session set container=<PDB명>;" 명령어로 접속하고자하는 PDB로 접속하는 방법입니다.

 

2) tnsnames.ora 파일 세팅후 @TNS 로 접속

tnsnames.ora 파일에 CDB나 PDB 정보를 설정하고, 그 이름을 사용해서 접속하는 방식입니다.

 

 

위는 sys 유저로 접속하는 예시라서 뒤에 "as sysdba" 가 붙었습니다.

scott 유저로 접속하는 경우는 "sqlplus scott/tiger@PDB1" 이라고 하면 됩니다.

 

 

3) Easy Connect 방식으로 접속

tnsnames 구성할 필요 없이 클라이언트 애플리케이션에서 직접 Oracle 데이터베이스에 대한 연결 주소를 지정할 수 있습니다 .

이 방법은 tnsnames.ora 파일을 생성하고 관리할 필요가 없다는 점에서 편리합니다. DB에 접속할 때 호스트 이름과 포트 번호를 지정하면 됩니다.

예를 들어, 호스트 이름이 shobeen이고 포트 번호가 1521인 서버에 있는 sales_us 데이터베이스에 연결하려고 한다면 다음과 같이 명령어를 실행하면 됩니다.

sqlplus system/admin@//shobeen:1521/sales_us

 

  • 다음 형식을 사용하여 SQL 연결 URL 문자열을 지정

//host[:port][/service_name]

//shobeen:1521/sales_us

  • Alternatively, specify the SQL connect information as an Oracle Net keyword-value pair.
  • Oracle Net 설정과 같이 SQL 연결 정보를 지정

(CONNECT_DATA=(SERVICE_NAME=sales_us)))”

“(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp) (HOST=shobeen) (PORT=1521))

 

 

 

 

4) TWO_TASK 설정해서 접속

 

TWO_TASK 환경변수를 설정해서 하는 방식은 사실 위 2)번 방식으로 tnsnames.ora 파일이 세팅되어 있을때 사용가능한 방식입니다.

TWO_TASK 환경변수가 하는 역할이 sqlplus 접속시 뒤에 "@TNS명" 을 안붙혀도 붙힌 것처럼 효과를 주는 것밖에는 없기 때문입니다.

 

 

만약, tnsnames.ora 파일에 PDB1 이 TNS 로 등록되어 있지 않으면

"ORA-12154: TNS:could not resolve the connect identifier specified" 에러가 발생합니다.

 

 

SQL*Plus 접속이 많은 경우, 좀 더 편하게 접속하고자 하는 경우는

위 3)번 Easy Connect 방식의 접속 커맨드를 alias 로 아래와 같이 만들어서 .profile 같은 곳에 넣어두고

이 alias 를 사용하면 아주 편합니다.

 

alias pdb1='sqlplus sys@localhost/PDB1 as sysdba'
alias pdb2='sqlplus sys@localhost/PDB2 as sysdba'
alias pdb3='sqlplus sys@localhost/PDB3 as sysdba'
alias pdb1_scott='sqlplus scott/tiger@localhost/PDB1'

 

 

 

+ Recent posts