RDBMS(MariaDB)에 대용량 데이터(사천팔백만건)를 스파크로 넣어보자

Jeonghak Cho·2025년 3월 25일

Spark

목록 보기
7/12

📗RDBMS(MariaDB)에 대용량 데이터(사천팔백만건)를 스파크로 넣어보자

파일 크기가 5GB에 달하는 사천팔백만건에 달하는 데이터를 마리아디비에 적재하는데 걸리는 시간은 9분 남짓 걸렸다. 시스템의 환경 (CPU 성능, 개수, 메모리, 노드 수)에 따라 많은 차이가 날 것이다.

  • 대용량 데이터 처리에 대한 경험
    • 소스와 싱크 연결
    • 대용량 데이터 적재
    • RDBMS 데이터 쓰기
    • RDBMS 데이터 쓰기 속도 확인
    • 대용량 데이터 크기 측정

🔗[목차]

프로비저닝

마리아디비, 스파크 설치

도커 컨테이너로 두 애플리케이션 (마리아디비, 스파크) 를 설치한다. 네트워크를 동일하게 처리해야 한다.

d network create mynetwork

docker run \
--name mariadb \
-e MYSQL_ROOT_PASSWORD=1234 \
--network mynetwork \
-p 3306:3306 -d mariadb

docker run -d \
--name spark-master \
-p 8080:8080 \
-p 7077:7077 \
-p 4040:4040 \
--network mynetwork \
-v $(pwd):/workspace \
bitnami/spark:latest

도커 실행 상태 확인

ubuntu@DESKTOP-SCOK45O:~/myspark$ d ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS

  NAMES
21821ec181c9   bitnami/spark:latest   "/opt/bitnami/script…"   30 minutes ago   Up 30 minutes   0.0.0.0:4040->4040/tcp, [::]:4040->4040/tcp, 0.0.0.0:7077->7077/tcp, [::]:7077->7077/tcp, 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp   spark-master
8d33b712bf9f   mariadb                "docker-entrypoint.s…"   31 minutes ago   Up 31 minutes   0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp
  mariadb

마리아디비 내부 IP 확인

ubuntu@DESKTOP-SCOK45O:~/myspark$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mariadb
172.18.0.2

환경 테스트

spark-shell을 JDBC 드라이버를 파라미터로 접속

spark-shell --jars /workspace/mariadb-java-client-2.6.2.jar

연결 변수 설정

val jdbcUrl = "jdbc:mysql://172.18.0.2:3306/mysql" 
val dbTable = "user" 
val dbProperties = new java.util.Properties()
dbProperties.setProperty("user", "root")
dbProperties.setProperty("password", "1234")
dbProperties.setProperty("driver", "org.mariadb.jdbc.Driver")

데이터 로드

val df = spark.read.jdbc(jdbcUrl, dbTable, dbProperties)

데이터 건 수 보기

scala> df.count()
res6: Long = 6

스키마 보기

scala> df.printSchema()
root
 |-- Host: string (nullable = true)
 |-- User: string (nullable = true)
 |-- Password: string (nullable = true)
 |-- Select_priv: string (nullable = true)

데이터 조회

scala> df.select("User","Host").show(10, true)
+--------------------+--------------------+
|                User|                Host|
+--------------------+--------------------+
|root             ...|%                ...|
|healthcheck      ...|127.0.0.1        ...|
|healthcheck      ...|::1              ...|
|healthcheck      ...|localhost        ...|
|mariadb.sys      ...|localhost        ...|
|root             ...|localhost        ...|
+--------------------+--------------------+

자동 테이블 생성 후 insert

df.write.mode("overwrite").jdbc(jdbcUrl, "my_table", dbProperties)

CSV의 5GB (4천 8백만건) MariaDB 테이블 (myjob)에 삽입

4천 8백만건의 데이터을 가진 csv 파일 로드

scala> val df = spark.read.option("header", "true").csv("/workspace/job_summary.csv")
df: org.apache.spark.sql.DataFrame = [job_link: string, job_summary: string]

scala> df.count()
res3: Long = 48219735

처리 시간 9분

df.write.mode("overwrite").jdbc(jdbcUrl, "myjob", dbProperties)

MariaDB에 접속하여 데이터 확인

MariaDB [mysql]> select * from myjob limit 10;
+------------------------------------------------------+-------------+
| job_link                                             | job_summary |
+------------------------------------------------------+-------------+
| Education Requirements                               | NULL        |
| Board Certified/Board Eligible in Emergency Medicine | NULL        |
| ACLS certified                                       | NULL        |
| Experience                                           | NULL        |
| Experience with LMR                                  | NULL        |
| 3 years of emergency room experience preferred       | NULL        |
| Experience with EPIC preferred.                      | NULL        |
| Primary Location                                     | NULL        |
| MA-Oak Bluffs-MVH Martha's Vineyard Hospital         | NULL        |
| Work Locations                                       | NULL        |
+------------------------------------------------------+-------------+
10 rows in set (0.001 sec)

데이터 건수 조회

건수(사천팔백만건) 조회하는데 1분 6초 걸림

MariaDB [mysql]> select count(*) from myjob;
+----------+
| count(*) |
+----------+
| 48219735 |
+----------+
1 row in set (1 min 6.746 sec)

du -sh /var/lib/mysql/mysql

데이터베이스 크기 확인

root@8d33b712bf9f:/var/lib/mysql/mysql# du -sh /var/lib/mysql/mysql
5.8G    /var/lib/mysql/mysql

SQL로 파일 크기 확인

MariaDB [mysql]> SELECT table_name, round((data_length + index_length) / 1024 / 1024, 2) AS size_mb
    -> FROM information_schema.tables
    -> WHERE table_schema = 'mysql' AND table_name = 'myjob';
+------------+---------+
| table_name | size_mb |
+------------+---------+
| myjob      | 5410.00 |
+------------+---------+
1 row in set (0.002 sec)

파일 크기 확인

root@8d33b712bf9f:/var/lib/mysql/mysql# ls -lh /var/lib/mysql/mysql/myjob.ibd
-rw-rw---- 1 mysql mysql 5.8G Mar 25 08:15 /var/lib/mysql/mysql/myjob.ibd

0개의 댓글