[ElasticSearch] 데이터 CRUD 하기 - With MySQL

조갱·2022년 10월 10일
0

ElasticSearch

목록 보기
1/7

작성하는 ElasticSearch는 7.15.3 버전을 기준으로 포스팅합니다.

ElasticSearch 와 Kibana 는 미리 설치해주세요.!

서론

대부분의 개발자들이 MySQL 은 많이 사용해봤지만, ElasticSearch 등 NoSQL은 많이 접하지 않았을거라 생각한다. 나 또한 ElasticSearch를 처음 접할 때 그래서 MySQL로 어떤 쿼리인데?가 가장 궁금했었다.

회사에서 통계를 MySQL -> ElasticSearch 로 이전하면서 (10/10 기준) 2개월동안 실무에서 사용했던 ES지식/쿼리를 MySQL 과 비교하여 설명해본다.

ES와 MySQL 에서 용어도 차이가 있으니, 용어에 대한 설명은 구글 검색을 통해 미리 익혀놓는게 좋다.

예제 데이터 모델

앞으로 (간단히) 사용하게 될 데이터 모델이다.

ES 사용 전 주의사항

  • ES는 MySQL 처럼 트랜잭션 개념이 없어서, Rollback, Commit 이 없다.
    쿼리한번 날리면 끝이니 항상 조심해서 사용하길.
  • ES의 인덱스 이름은 반드시 소문자로 시작해야한다. (Person -> person)

DDL (Data Definition Language)

CREATE TABLE (INDEX)

MySQL

  • FK의 constaint 는 귀찮아서 정의하지 않는다.
  • personId 는 직접 넣어주기로 한다. (Auto_Increment 안씀)
CREATE TABLE Person(
  personId INT(11) NOT NULL,
  name VARCHAR(20) NOT NULL,
  gender VARCHAR(1) NULL,
  age SMALLINT,
  CONSTRAINT personTable_PK PRIMARY KEY(personId)
);

CREATE TABLE Address(
  personId INT(11) NOT NULL,
  country VARCHAR(20) NOT NULL,
  city VARCHAR(20) NULL,
);

ES

  • ES는 기본적으로 FK 및 Join을 지원하지 않는다.
    • 이유는, MySQL은 관계에 중점을 두는 관계형 데이터베이스 (RDBMS) 인 반면에 ElasticSearch 같은 document 기반 NoSql 은 데이터 모델에 중점을 두기 때문에 Join연산은 고려되지 않는다.
    • (아마 어째어째 가능은 한걸로 아는데, 비용이 너무 커서 사용하지 않는걸로 안다.)
  • 따라서 Join 되는 테이블인 Address는 Nested 타입으로 비정규화 하여 저장한다.
  • 아래 shard의 개수는 3개로 했는데, 일반적으로는 노드의 개수로 설정한다.
    • GET /_nodes/stats 를 통해 노드의 개수를 확인해보자.
  • 아래 쿼리 수행 후 아래와 같이 응답이 오면 정상적으로 만들어진 것이다.
PUT /person
{
  "settings": {
    "number_of_shards": 3, << 반드시 GET /_nodes/stats 에서 나온 노드의 개수 입력
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "_class": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "personId": {
        "type": "keyword"
      },
      "name": {
        "type": "keyword"
      },
      "gender": {
        "type": "keyword"
      },
      "age": {
        "type": "integer"
      },
      "address": {
        "type": "nested",
        "properties": {
          "personId": {
            "type": "keyword"
          },
          "country": {
            "type": "keyword"
          },
          "city": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

DROP TABLE (DELETE INDEX)

MySQL

DROP TABLE `Person`;
DROP TABLE `Address`;

ES

DELETE /person

DML (Data Manipulation Language)

Insert (Create)

MySQL

INSERT INTO Person(personId, name, gender, age)
VALUES(1, '김이름', 'M', 27);
INSERT INTO Address(personId, country, city)
VALUES(1, 'KR', 'Suwon');

ES

PUT person/_doc/1
{
  "name":"김이름",
  "gender":"M",
  "age": 27,
  "address": {
    "personId": 1,
    "country": "KR",
    "city": "Suwon"
  }
}

Select (Read)

MySQL

SELECT *
FROM Person
WHERE age = 27;

ES

GET person/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {"age": "27"}
        }
      ]
    }
  }
}

Update

MySQL

UPDATE Person
SET age = 28
WHERE personId = 1

ES

  • ES 에서 update는 가급적 하지 않는것이 좋다.
    • 가장 큰 이유는 역인덱싱 (reverse-indexing) 을 다시 해야 하는 비용 때문.
    • 따라서 document 기반의 NoSql 은 update가 주로 되지 않고, insert/select 가 주로 되는 상황에 적합하다.
  • 아래 사진과 같은 결과를 받으면 성공이다.
    응답값에서 볼 수 있듯, document의 버전이 2 로 올랐는데, 기존 문서 (version: 1)에서 1회 수정됐음을 의미한다.
PUT person/_doc/1
{
  "age": 28
}

Delete

MySQL

DELETE
FROM Person
WHERE personId = 1

ES

  • 다시 한번 얘기하지만, ES에는 트랜잭션 개념이 없어서 한번 DELETE 하면 끝이다. rollback 같은거 없다. 반드시 확인하고 또 확인하고 삭제할 것
  • 아래 사진과 같이 나오면 성공이다.
DELETE /person/_doc/1

오늘은 MySQL 과 ES를 비교하며 가장 간단한 CRUD 쿼리에 대해 알아보았다. 앞으로는 조금 더 복잡한 쿼리와 집계함수에 대해 알아본다.

Reference
Nested: https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html

profile
A fast learner.

0개의 댓글