본문 바로가기

카테고리 없음

Bulk Insert

이 포스팅은 제가 작성한 UPbrella 프로젝트의 기술 블로그에 작성한 대용량 데이터 삽입 적용기 포스팅을 옮겨온 것입니다.

1. 문제 정의

데이터 베이스 성능을 개선하는 것은 품질 좋은 서버를 유지하기 위해서 필수적입니다.

하지만 개발자들이 수작업으로 데이터를 삽입한 후 테스트 하는 것은 한계가 있습니다.

따라서 업브렐라 개발팀은 Data Bulk Insert를 통해 DB에 대용량의 데이터를 삽입하고 성능 개선을 해보도록 하겠습니다.

2. Bulk Insert

2 - 1 데이터 만들기

우선 간단한 테이블인 협업지점 분류에 대한 데이터를 만들어보겠습니다.

classification 테이블은 id, type, name, latitude, longitude를 필드로 가지고 있는데, 이에 해당하는 데이터를 만들어 보겠습니다.

private static void makeStoreMeta() {
        String filePath = "store_meta.csv";
        Random random = new Random();

        try (FileWriter writer = new FileWriter(filePath)) {
            writer.append("id,classification_id,sub_classification_id,activated,deleted,name,category,latitude,longitude,password");
            writer.append("\n");

            for (int i = 1; i <= 1_000_000; i++) {
                writer.append(Integer.toString(i));
                writer.append(",");
                writer.append(Long.toString(random.nextLong() % 1000)); // classification_id
                writer.append(",");
                writer.append(Long.toString(random.nextLong() % 1000)); // sub_classification_id
                writer.append(",");
                writer.append(Integer.toString(random.nextInt(2))); // activated
                writer.append(",");
                writer.append(Integer.toString(random.nextInt(2))); // deleted
                writer.append(",");
                writer.append("Store_" + i); // name
                writer.append(",");
                writer.append("Category_" + (random.nextInt(10) + 1)); // category
                writer.append(",");
                writer.append(random.nextDouble() * 180 - 90 + ""); // latitude
                writer.append(",");
                writer.append(random.nextDouble() * 360 - 180 + ""); // longitude
                writer.append(",");
                writer.append("Password_" + i); // password
                writer.append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("CSV file created successfully at: " + filePath);
    }

위와 같이 FileWriter를 통해 백만건의 랜덤한 Classification을 생성하였습니다.

2 - 2 데이터 전송

이와 같은 대용량의 데이터를 서버에서 직접 만들 경우, CPU 부족 현상으로 서버가 다운될 우려가 있어 데이터 생성은 로컬에서 진행하였습니다.

이제 scp 명령어를 통해 데이터를 서버에 전송해주겠습니다.

scp -p classification.csv ubuntu@127.0.0.1:~/classification.csv

127.0.0.1에 서버의 ip를 기입하면 전송을 완료할 수 있습니다.

scp : 파일 전송 명령어

p : 작성, 수정한 날짜를 보존함

clsasification.csv 전송하려는 파일 명

ubuntu@127.0.0.1 : 서버의 사용자명과 서버의 ip

:~/classification.csv : 파일이 저장될 위치

2 - 3 MySQL에 데이터 삽입

MySQL에서 파일을 Load해서 파일에 맞게 데이터를 INSERT 하기 위해서는 특정 위치에 해당 파일이 위치해야 합니다.

파일을 MySQL이 읽을 수 있는 위치로 이동시켜 줍니다.

sudo mv classification.csv /var/lib/mysql-files/

이제 파일을 이동시켰으니 데이터를 삽입해보도록 하겠습니다.

LOAD DATA INFILE '/var/lib/mysql-files/classification.csv' INTO TABLE classification
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;

csv 파일을 생성할 때, 맨 윗 줄에 필드에 대한 설명을 적었기 때문에 ignore 1 rows를 해줍니다.

field 의 구분은 , 로 진행하고

line의 구분은 \n 으로 진행해줍니다.

3 마치며

이번 게시글을 통해 대용량의 데이터를 삽입하는 방법을 알아보았습니다.

다음 게시글에서는 대용량의 데이터를 통해 성능이 좋지 않은 API를 판별해보고 개선하는 방법에 대해 알아보겠습니다.