1. JMeter 란

Apache JMeter™ 애플리케이션은 기능을 부하 테스트하고 성능을 측정는 100% 순수 Java 오픈 소스 소프트웨어입니다. 원래 웹 애플리케이션 테스트용으로 설계되었지만 이후 다른 테스트 기능으로 확장되었습니다.

 

2. JMeter 설치

1) 설치환경

  • OS : Window11
  • JAVA : 17.0.6
  • Apache JMeter 5.6.3 (Requires Java 8+)

2) 다운로드

https://jmeter.apache.org/download_jmeter.cgi 페이지에서 apache-jmeter-5.6.3.zip 다운로드

 

3) 설치

다운받은 파일을 압축 해제한 후

apache-jmeter-5.6.3\bin 디렉토리에 있는 jmeter.bat 파일을 실행시킨다.

jmeter.bat 파일을 실행하면 아래와 같은 화면이 나타난다.

3. JMeter 사용법

테스트 계획은 JMeter 스크립트이며, 부하 테스트의 흐름을 결정한다.

이 JMeter 튜토리얼에서는 BlazeMeter에서  사용하는 데모를 로드 테스트하여 Simple이라는 모의 여행사를 시뮬레이션한다. Simple Travel Agency를 사용하면 항공편을 검색하고 선택할 수 있으며 JMeter를 통해 시뮬레이션한다.

 

첫 번째 스크립트 : 이용 가능한 항공편을 검색 시나리오

 

Thread Groups :

테스트 스크립트 작성을 시작하려면 테스트 계획에 스레드 그룹을 추가한다.
스레드 그룹은 사용자 흐름을 결정하고 사용자가 앱에서 행동하는 방식을 시뮬레이션한다.

각 스레드는 사용자를 나타낸다.
테스트 계획을 마우스 오른쪽 버튼으로 클릭하고 "Threads(Users)"를 선택한 다음 "Thread Group"을 선택한다.

 

- Configure the Thread Group by setting:

  • Name: 사용자 정의 이름을 제공하거나 원하는 경우 기본 이름을 "Thread Group"으로 둔다.
  • Number of Threads: 테스트 사용자(스레드) 수
  • Ramp-up Period: 사용자를 추가하는 속도(초). 예를 들어 0으로 설정하면 모든 사용자가 즉시 시작다.  쓰레드가 10개이고 Ramp-up Period가 50이면 Thread를 50초 동안 차례대로 생성하라'는 의미이다. 즉, 5초(50초/10개)마다 Thread를 하나씩 생성하는 것과 같은 의미이다.

  • Loop Count: 테스트를 반복하는 횟수

Samplers

데모 사이트에 HTTP 요청을 보내려고 하므로 HTTP 요청 샘플러를 추가한다.
스레드 그룹을 마우스 오른쪽 버튼으로 클릭하고 "추가"를 선택한 다음 "샘플러"를 선택한 다음 "HTTP 요청"을 선택다.

 

아래와 같이 샘플러를 구성한다.

  • Name: 사용자가 정한 이름을 입력하거나 기본 "HTTP Request "라는 이름을 그대로 사용 
  • Server Name or IP: 서버의 DNS 이름 또는 IP 주소입니다. 본문에서는 blazedemo.com 입력
  • HTTP를 통해서만 접속할 수 있는 웹사이트는 브라우저에서 안전하지 않은 것으로 표시되고 검색 엔진 결과에서 제외되므로 프로토콜을 "https"로 설정 

 

Timers

사용자가 웹사이트나 앱을 클릭하면 일시 중지와 지연이 발생한다. 이는 타이머를 사용하여 시뮬레이션할 수 있다.
상수 타이머가 가장 일반적이다. 요청 사이에 대기할 시간(밀리초)을 결정한한다.
"HTTP Request" 마우스 오른쪽 버튼으로 클릭하고 "Add"를 선택한 다음 "Timer"를 선택한 다음 "Constant Timer"를 선택한다.

본 문성에서는 300 miliseconds 를 입력한다.

 

Listeners

로깅 및 디버깅 정보를 포함하여 결과를 표시하는 기록 메커니즘인 리스너를 통해 테스트를 실행한 후 결과를 확인한다.

View Results Tree는 가장 일반적인 리스너다.
"Thread Group"을 마우스 오른쪽 버튼으로 클릭하고 "Add"를 선택한 다음 "Listener"를 선택한
다음 "View Results Tree"를 선택한다.

 

이제 파일을 저장한다. 본 문서에서는 "Test Plan.jmx" 파일명으로 저장하였다.

 

테스트를 실행하려면 상단의 녹색 화살표를 클릭한다. 테스트 실행이 완료되면 리스너에서 결과를 볼 수 있다.
분 문서에서는 결과에 녹색 아이콘이 표시되므로 테스트가 성공한 것을 확인할 수 있다. 오른쪽 창에서는 로드 시간, 연결 시간, 오류, 요청 데이터, 응답 데이터 등과 같은 더 자세한 결과를 볼 수 있고, 결과를 저장할 수도 있다.

 

두 번째 스크립트 : 항공편 검색 후 항공편 선택 시나리오

두 번째는 매개변수를 추가한 JMeter 시나리오입니다.

첫 번째 스크립트는 단순히 항공편을 검색한 반면, 두 번째 스크립트는 항공편을 검색한 후 항공편을 선택하는 시나리오입니다.

 

웹 브라우저에서 항공편을 검색하고 선택한 항공편 옆에 있는 "Find Flights" 버튼을 클릭하면 "/reserve.php"가 호출됩니다.

JMeterd에서 HTTP 샘플러를 추가합니다. 본 문서에서는 "reserve" HTTP 샘플러를 추가했습니다. Server Name or IP란에 "blazedemo.com"을 입력하고, "Path" 필드에 "reserve.php"를 추가한다. 이렇게 하면 샘플러가 "blazedemo.com/reserve.php"의 전체 URL을 구축하도록 지시하게 된다. 

다음으로 선택에 필요한 매개변수를 추가한다. (웹 브라우저의 개발자 도구(크롬 브라우저 : F12)를 사용하여 파라미터명을 찾을 수 있다.) 이 페이지에서 "fromPort" 및 "toPort"를 지정하고, 각각 "Boston"과 "London"으로 입력한다.

 

추가적인 정보를 보기 위해 "View Results in Table" 리스너를 추가한다.
이는 홈 페이지를 방문한 다음 두 개의 매개변수를 예약 페이지로 보내는 Test Plan 이다.

저장 후 실행하면 아래와 같은 결과 화면을 볼 수 있다.

 

 세 번째 스크립트 : 항공편 검색 후 항공편 선택 시나리오

긴 사용자 사용 흐름을 생성해야 한다면 시간이 오래 걸릴 수 있습니다.

따라서 스크립트를 작성하는 것보다 더 좋은 방법은 스크립트를 녹음하는 것입니다. JMeter 레코더 또는 BlazeMeter Chrome 확장 프로그램으로 녹음을 할 수 있습니다. Chrome 스토어에서 무료로 사용할 수 있는 BlazeMeter 확장 프로그램은 트래픽을 리디렉션하기 위해 프록시를 설정해야 하는 JMeter 확장 프로그램보다 사용자 친화적입니다.

Chrome을 통해 녹음을 시작하고 클릭하여 테스트하려는 사용자 시나리오를 시뮬레이션합니다. 완료되면 녹음을 중지하고 필요에 따라 편집을 할 수 있습니다.

 

크롬 확장 설치

BlazeMeter 확장 프로그램을 설치한 후, 크롬 브라우저의 우측 상단에 BlazeMeter를 클릭한다.

 

https://blazedemo.com/ 에 접속하여, 비행편을 검색하고 검색된 비행편을 선택한 후 예약 정보를 입력한 다음,

녹음 중지 버튼을 클릭한다.

녹음을 완료한 후 "Save ..." 버튼을 클릭하여 "Jmeter(JMX)" 선택한 다음 "Save"한다.

 

Now add a listener and run the test.

 

 

환경

- window10

- MySQL version : 8.0.32

 

The Binary Log

바이너리 로그에는 테이블 생성 작업이나 테이블 데이터 변경과 같은 데이터베이스 변경을 설명하는 "이벤트"가 포함되어 있습니다. 또한 행 기반 로깅을 사용하지 않는 한 잠재적으로 변경했을 수 있는 명령문(예: 행과 일치하지 않는 DELETE)에 대한 이벤트도 포함됩니다. 바이너리 로그에는 각 명령문이 업데이트된 데이터에 소요된 시간에 대한 정보도 포함되어 있습니다. 바이너리 로그에는 두 가지 중요한 목적이 있습니다.

  • 복제의 경우 복제 소스 서버의 바이너리 로그는 복제본으로 전송될 데이터 변경 사항에 대한 기록을 제공합니다. 소스는 바이너리 로그에 포함된 정보를 복제본으로 전송하며, 복제본은 해당 트랜잭션을 재현하여 소스에서 수행된 것과 동일한 데이터 변경을 수행합니다.
  • 특정 데이터 복구 작업에는 바이너리 로그를 사용해야 합니다. 백업이 복원된 후에는 백업 이후에 기록된 바이너리 로그의 이벤트가 다시 실행됩니다. 이러한 이벤트는 백업 시점부터 데이터베이스를 최신 상태로 유지합니다. 

# binlog 관련 변수

  • log_bin : 서버의 바이너리 로깅 상태를 활성화(ON) 또는 비활성화(OFF)로 표시. 바이너리 로깅이 활성화되면 서버는 데이터를 변경하는 모든 명령문을 백업 및 복제에 사용되는 바이너리 로그에 기록. ON은 바이너리 로그를 사용할 수 있음을 의미하고, OFF는 사용 중이 아님을 의미
  • log_bin_basename : 바이너리 로그 파일의 경로와 기본 이름. 최대 변수 길이는 256. 기본 위치는 데이터 디렉터리
  • log_bin_index : binlog 파일의 이름을 저장하고 있는 파일
  • bin_log_format : ROW / MIXED / STATEMENT
  • max_binlog_size : 바이너리 로그에 쓰기로 인해 현재 로그 파일 크기가 이 변수의 값을 초과하는 경우 서버는 현재 파일을 닫고 다음 파일을 엽니다. 최소값은 4096바이트입니다. 최대값과 기본값은 1GB입니다. 
  • sql_log_bin : 현재 세션에 대해 바이너리 로그에 대한 로깅 활성화 여부를 제어(log_bin 은 활성화된 상태에서). 기본값은 ON. 현재 세션에 대해 로깅을 비활성화하거나 활성화하려면 sql_log_bin 변수를 OFF 또는 ON으로 설정

binary 로그 확인

mysqlbinlog 유틸리티로 binary log 파일을 텍스트 형식으로 확인할 수 있다.

 

[사용법]
mysqlbinlog "bin 로그경로\binlog 파일명" > binlog.sql

 

[예시] 아래 예시는 Window10에 설치된 MySQL의 binary log 내용을 확인하는 명령어이다.

mysqlbinlog C:\ProgramData\MySQL\MySQL Server 8.0\Data\DESKTOP-bin.000115 > binlog.sql

 

 

bin_log_format 비교

bin_log_format 설정에는 ROW, MIXED, STATEMENT 세가지가 있는데 각각의 차이점은 아래와 같다.

 

  • STATEMENT :  명령문 기반 로깅
  • ROW : 행 기반 로깅. (default)
  • MIXED : STATEMENT와 ROW 혼합 형식 로깅. 기본적으로 STATEMENT 기반 로깅이 사용되지만 특정 경우에는  ROW 기반으로 로깅.

STATEMENT와 ROW 기반 로깅.

1) STATEMENT기반 로깅

STATEMENT 기반의 로깅 설정 시 생성된 binary log 파일을 mysqlbinlog 명령어로 수행해 보면 아래와 같은 형식으로 저장되어 있는 것을 볼 수 있다.

 

 

2) ROW 기반 로깅

ROW 기반의 로깅 설정 시 생성된 binary log 파일을 mysqlbinlog 명령어로 수행해 보면 아래와 같은 형식으로 저장되어 있는 것을 볼 수 있다.

 

 

3) MIXED기반 로깅

기본적으로 Statement-Based Format으로 기록되나, 필요에 따라 Row-base Format으로 Binary Log에 기록된다.

UUID()함수, sysdate() 함수 등 사용 시에는 ROW 기반으로 수행된다.

now(), current_timestamp() 는 STATEMENT-Based Format으로 기록된다. Master와 Slave 간 데이터 차이가 발생하지 않는 것은 binlog의 TIMESTAMP 값으로 설정하는 것 같다.

 

[ sysdate() 함수 사용 시 binary log]

 

[ now() 함수 사용 시 binary log]

 

 

DB 접속과 관련된 환경변수와 상태변수를 나타낸다.

환경 변수는 show variables like '환경변수'로 확인할 수 있고, 상태변수는 show status like '상태변수' 로 확인할 수 있다.

변수 설명 구분
max_connections MySQL 서버가 허용하는 MySQL 클라이언트 동시 연결 최대값.
max_connections +1"로 SUPER 권한을 가진 사용자(예 : root) +1의 연결 예약
환경변수
Max_used_connections 지금까지 기록된 동시 연결 최대 수 상태변수
Threads_connected 현재 열려있는 연결 수 상태변수
Threads_created 연결을 처리하기 위해 생성된 스레드 상태변수
Threads_running 작동중인 스레드 상태변수
Threads_cached   상태변수
Thread_cache_size 재사용을 위해 서버가 캐시해야 하는 스레드 수 환경변수

 

Thread_cache_size

재사용을 위해 서버가 캐시해야 하는 스레드 수입니다. 클라이언트의 연결이 끊어지면 해당 스레드가 thread_cache_size보다 적은 경우 클라이언트의 스레드가 캐시에 저장됩니다. 스레드에 대한 요청은 가능하면 캐시에서 가져온 스레드를 재사용하여 충족되며, 캐시가 비어 있는 경우에만 새 스레드가 생성됩니다. 새로운 연결이 많은 경우 성능을 향상시키기 위해 이 변수를 늘릴 수 있습니다. 일반적으로 눈에 띄는 성능 향상을 제공하지 않습니다. 그러나 서버가 초당 수백 개의 연결을 확인하는 경우 일반적으로 대부분의 새 연결이 캐시된 스레드를 사용할 수 있도록 thread_cache_size를 충분히 높게 설정해야 합니다. Connections 및 Threads_created 상태 변수 간의 차이점을 조사하면 스레드 캐시가 얼마나 효율적인지 확인할 수 있습니다. 

 

기본값은 다음 수식을 기반으로 하며 한도는 100입니다.

 

8 + (max_connections / 100)

 

 

 

 

참고)

Based on the info in the MySQL Documentation you should do the following: Find out what the highest number of simultaneous connections mysqld has had using ConnectionsThreads_created, and Max_used_connections,

  • SHOW GLOBAL STATUS LIKE 'Connections';
  • SHOW GLOBAL STATUS LIKE 'Threads_created';
  • SHOW GLOBAL STATUS LIKE 'Max_used_connections';

Try calculating the following

Threads_created / Connections : If this is over 0.01, then increase thread_cache_size. At the very least, thread_cache_size should be greater than Max_used_connections.

 

 

Questions / Uptime / Connections / Max_used_connections
Uptime 은 서버가 가동되고 나서 초를 의미하고, Questions는 서버가 가동되고 나서 수행된 쿼리의 수이다.
Connections는 서버 가동되고 나서 연결시도된 수치다.(현재 연결수는 Threads_connected)
Max_used_connections는 서버 가동 이후 최대 동시 연결 수치이다.
 
  • Questions/Uptime = 초당 쿼리수
  • Connections / Uptime = 초당 연결수
  • Questions / Connections = 연결당 쿼리 처리수
 
놀고 있는 시간과 바쁜시간의 차이를 알기위해 1분간격으로 측정한다면 다음과 같은 내용 확인이 가능하다.
1분간의 초당 쿼리 처리건수 = (현재의 Questions – 1분전의 Question) / (현재의 Uptime / 1분전의 Uptime)
 
참조 :

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:

+ Recent posts