Search

Row Generation 성능 비교 - SingleStore, Oracle, MySQL, PostgreSQL

문서번호 : 11-2132661

개요

이전 포스트에서 Row Generation 방법을 소개해 드렸습니다.
이번 포스트에서는 각 DB 마다 Row Generation 성능을 간단하게 비교하도록 하겠습니다.
비교 테스트에 사용한 장비는 8vCPU, 16GB 의 사양으로 Hands-On 테스트에 사용했던 장비를 그대로 사용하였고 여기에 Oracle XE 21c 를 추가로 설치했습니다.

Oracle

Oracle XE 21c는 SGA+PGA 합쳐서 2GB 를 넘지 못하도록 제약이 걸려 있습니다. 따라서 불가피하게 PGA가 3000MB 로 설정되어 있는 Autonomous Database 에서도 같이 테스트를 진행했습니다.

Oracle XE 21c - 8cpu, pga_aggregate_target=512m

1억건은 메모리 부족으로 에러가 발생합니다.
에러가 안나는 최대 row 갯수는 220만건 정도로 0.5 초 정도 소요됩니다.
Recursive With 구문으로 천만건 생성하는데 2분 7초 정도 소요되었습니다.
SQL> select count(*) from (select rownum from dual connect by level <= 100000000); select count(*) from (select rownum from dual connect by level <= 100000000) * ERROR at line 1: ORA-30009: Not enough memory for CONNECT BY operation SQL> select count(*) from (select rownum from dual connect by level <= 2200000); COUNT(*) ---------- 2200000 Elapsed: 00:00:00.54 SQL> with t(n) as ( 2 select 1 as n from dual 3 union all 4 select n+1 as n from t where n < 10000000 5 ) 6 select count(*) from t; COUNT(*) ---------- 10000000 Elapsed: 00:02:07.19
SQL
복사

Oracle Autonomous Database 19c - pga_aggregate_target=3000m

Oracle Autonomous Database 에서는 재귀 쿼리로 천만건 생성하는데 3.21 초 정도 소요되었습니다.
Recursive With 구문으로는 천만건 생성에 1분 40초 정도 소요되었습니다.
SQL> show parameter pga_aggregate_target; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ pga_aggregate_target big integer 3000M SQL> select count(*) from (select rownum from dual connect by level <= 10000000); COUNT(*) ---------- 10000000 Elapsed: 00:00:03.21 SQL> with t(n) as ( 2 select 1 as n from dual 3 union all 4 select n+1 as n from t where n < 10000000 5 ) 6 select count(*) from t; COUNT(*) ---------- 10000000 Elapsed: 00:01:40.69
SQL
복사

MySQL

MySQL 에서는 cte max recursive depth 를 기본 1000 에서 1억으로 우선 늘립니다.
Recursive CTE 를 이용해서 천만건 row 를 생성하는데 1.73초 수행되었습니다.
Recursive CTE 를 이용해서 1억건 row 를 생성하는데 1분 3초가 소요되었습니다.
mysql> set @@cte_max_recursion_depth=100000000; Query OK, 0 rows affected (0.00 sec) mysql> with recursive t(n) as ( -> select 1 as n -> union all -> select n+1 as n from t where n < 10000000 -> ) -> select count(*) from t; +----------+ | count(*) | +----------+ | 10000000 | +----------+ 1 row in set (1.73 sec) mysql> with recursive t(n) as ( -> select 1 as n -> union all -> select n+1 as n from t where n < 100000000 -> ) -> select count(*) from t; +-----------+ | count(*) | +-----------+ | 100000000 | +-----------+ 1 row in set (1 min 3.85 sec)
SQL
복사

PostgreSQL

PostgreSQL 은 generate_series 를 이용해 천만건 생성하는데 1.5초가 소요되었습니다.
동일한 방법으로 1억건 생성할 때는 15.4초가 걸렸습니다.
Recursive CTE 를 이용해서 천만건 row 를 생성하는데는 4.6초, 1억건 생성할 경우는 47초가 소요되었습니다.
postgres=# select count(*) from generate_series(1, 10000000); count ---------- 10000000 (1 row) Time: 1583.327 ms (00:01.583) postgres=# select count(*) from generate_series(1, 100000000); count ----------- 100000000 (1 row) Time: 15474.199 ms (00:15.474) postgres=# with recursive t(n) as ( postgres(# select 1 as n postgres(# union all postgres(# select n+1 as n from t where n < 10000000 postgres(# ) postgres-# select count(*) from t; count ---------- 10000000 (1 row) Time: 4682.084 ms (00:04.682) postgres=# with recursive t(n) as ( postgres(# select 1 as n postgres(# union all postgres(# select n+1 as n from t where n < 100000000 postgres(# ) postgres-# select count(*) from t; count ----------- 100000000 (1 row) Time: 47140.642 ms (00:47.141)
SQL
복사

SingleStore

이제 SingleStore 차례입니다. SingleStore 는 바로 1억건부터 시작해서 1억건 단위로 올려보겠습니다.
1억건에 0.86초 ~ 6억건에 6.4초정도 소요되었습니다.
7억건 생성시 메모리 부족 에러가 발생했습니다.
singlestore> select count(*) from gen_rows(100000000); +-----------+ | count(*) | +-----------+ | 100000000 | +-----------+ 1 row in set (0.86 sec) singlestore> select count(*) from gen_rows(200000000); +-----------+ | count(*) | +-----------+ | 200000000 | +-----------+ 1 row in set (1.85 sec) singlestore> select count(*) from gen_rows(300000000); +-----------+ | count(*) | +-----------+ | 300000000 | +-----------+ 1 row in set (2.60 sec) singlestore> select count(*) from gen_rows(400000000); +-----------+ | count(*) | +-----------+ | 400000000 | +-----------+ 1 row in set (4.03 sec) singlestore> select count(*) from gen_rows(500000000); +-----------+ | count(*) | +-----------+ | 500000000 | +-----------+ 1 row in set (4.44 sec) singlestore> select count(*) from gen_rows(600000000); +-----------+ | count(*) | +-----------+ | 600000000 | +-----------+ 1 row in set (6.40 sec) singlestore> select count(*) from gen_rows(700000000); ERROR 1712 (HY000): Memory used by MemSQL (8328.62 Mb) has reached the 'maximum_memory' setting (14141 Mb) on this node. Possible causes include (1) available query execution memory has been used up for table memory (in use table memory: 8058.62 Mb) and (2) the query is large and complex and requires more query execution memory than is available (in use query execution memory 0.00 Mb). See https://docs.memsql.com/troubleshooting/latest/memory-errors for additional information.
SQL
복사

마무리

실제 운영환경에서 임의의 Row 를 몇억건씩 만들어 사용할 일은 그리 많지 않을 것입니다. 하지만 대량의 데이터를 만들고 수정하고 삭제하는 테스트는 매우 빈번하게 일어납니다.
SingleStore 는 다른 데이터베이스보다 수십배 많은 데이터를 처리하면서도 빠른 응답이 가능해 이런 테스트마저도 쾌적하게 진행할 수 있습니다.