[1] 데이터베이스 튜닝이란
데이터베이스 튜닝(Database Tuning) 이란 데이터베이스 어플리케이션, 데이터베이스 자체, 운영체제 등의 조정을 통하여 데이터베이스 시스템의 성능을 향상시키는 작업을 말한다. 데이터베이스 튜닝이 필요한 이유는 데이터베이스 시스템 운영 중에 다양한 어플리케이션의 도입과 데이터의 대용량화로 인해 데이터베이스 시스템의 성능이 저하될 수 있기 때문이다. 따라서 데이터베이스 튜닝을 통해 기존 데이터베이스 시스템에 존재하는 문제점을 정확히 분석하여, 높은 작업 처리량과 짧은 응답시간을 갖도록 하는 것이 중요하다.
데이터베이스 튜닝에서는 기존 시스템의 문제점 분석을 통해 튜닝의 정확한 목적과 대상을 정해야 한다. 그리고 실제와 유사한 환경에서 최소한의 반복 테스트를 통해 튜닝 이전보다 개선된 결과를 가져오도록 해야한다.
[2] 문제점 분석
Influxdb 활용해서 진행하는 프로젝트에서 특정 Grafana 대시보드 접속 시 로딩 시간이 유독 길었다.
왜 길었을까?
쿼리가 느려지는 이유 & Influxdb Volume
쿼리를 최적화하기 전, 튜닝의 정확한 목적과 대상을 정하기 위해 쿼리가 느려지는 원인을 분석해보자.
우선, Grafana 모니터링 대시보드의 데이터베이스별 로딩시간 중 cassandra 의 대시보드가 유독 로딩시간이 느려서 각 데이터베이스의 물리적인 파일 용량을 확인해보았다. 그 중 비약적으로 큰 용량을 가진 데이터베이스는 예상을 어긋나지 않고 DB_S 임을 확인할 수 있다.
쿼리에서 훑어봐야 하는 데이터가 많을수록 시간이 더 오래 소요되는 것은 당연하다.
Tuning 에 필요한 panel List up
- Grafana dashboard 에서 query tuning 을 우선적으로 해야 할 panel 및 query 선정
- 크롬 개발자 도구의 ‘Network’ 에서 Request 와 관련한 페이지 로딩 성능 및 해당 query 확인
- Checking downed instance of cassandra (각 그래프 패널명)
SELECT (100- mean(“usage_idle”)) FROM “cpu” WHERE “cpu” = ‘cpu-total’ AND time >= now() – 2d GROUP BY time(1m), “host”;SELECT (100- mean(“usage_idle”)) FROM “cpu”
—
” WHERE “cpu” = ‘cpu-total’ AND time >= now() – 2d GROUP BY time(1m), “host”;SELECT (100- mean(“usage_idle”)) FROM “cpu” WHERE “cpu” = ‘cpu-total’ AND time >= now() – 2d GROUP BY time(1m), “host”
- Tombstone Count For Query of Item Table
SELECT max(“TombstoneScannedHistogram_Max”) FROM “cassandra_Table” WHERE (“scope” = ‘item’) AND time >= now() – 2d GROUP BY time(1m), “host”
- ThreadPool:etc
SELECT mean(“ActiveTasks_Value”) FROM “cassandra_ThreadPools” WHERE (“scope” != ‘Native-Transport-Requests’
—
AND “scope” != ‘PerDiskMemtableFlushWriter_0’ AND “scope” != ‘GossipStage’) AND time >= now() – 2d GROUP BY time(10m), “scope”, “host”
[3] 공통적인 문제점 및 해결 방안
해결을 위해 Influxdb tuning test 를 진행했고, 다음은 진행한 Query 성능 향상 방안에 대한 내용이다.
- 문제점 : 144개 * 288개 * 1,006개 = 41,720,832 points
group by time(10m) query 의 row 개수 = 144개
group by tags > host의 개수 = 288개
group by tags > scope의 개수 = 1,006개
- 해결 방안 : 뽑아내는 데이터(points)가 무분별하게 많은 것을 줄이는 방안. 존재하는 호스트(서버 대수) 자체를 줄일 수는 없으니, select 하는 points 수 줄이기
- group by time(time interval) 조정 -> interval 이 s/m/h 등. 어떤 값이 가장 적합할지 고려
- continuous query
- 예시 – ThreadPool:etc
SELECT mean(“ActiveTasks_Value”) FROM “cassandra_ThreadPools” WHERE (“scope” != ‘Native-Transport-Requests’ AND “scope” != ‘MutationStage’ AND “scope” != ‘ReadRepairStage’
—
‘PerDiskMemtableFlushWriter_0’ AND “scope” != ‘GossipStage’) AND time >= ‘2021-07-10 00:00:00’ and time <= ‘2021-07-10 23:59:59’ GROUP BY time(10m), “scope“, “host“
쿼리 성능 비교
GROUP BY time() 구문에서 시간을 조절하면서 각 Query 문 성능에 대해 비교 분석해보았다.
- Query 01 – 1m/1d 단위
SELECT mean(“ActiveTasks_Value”) FROM “cassandra_ThreadPools” WHERE (“scope” != ‘Native-Transport-Requests’ AND “scope” != ‘MutationStage’
—
“scope” != ‘PerDiskMemtableFlushWriter_0’ AND “scope” != ‘GossipStage’) AND time >= ‘2021-07-10 00:00:00’ and time <= ‘2021-07-10 23:59:59’ GROUP BY time(1m), “scope”, “host”
60 * 24h = 1,440 row
- Query 02 – 10m/1d 단위
SELECT mean(“ActiveTasks_Value”) FROM “cassandra_ThreadPools” WHERE (“scope” != ‘Native-Transport-Requests’ AND “scope” != ‘MutationStage’
—
“scope” != ‘PerDiskMemtableFlushWriter_0’ AND “scope” != ‘GossipStage’) AND time >= ‘2021-07-10 00:00:00’ and time <= ‘2021-07-10 23:59:59’ GROUP BY time(10m), “scope”, “host”
6 * 24h = 144 row
- Query 03 – 30m/1d 단위
SELECT mean(“ActiveTasks_Value”) FROM “cassandra_ThreadPools” WHERE (“scope” != ‘Native-Transport-Requests’ AND “scope” != ‘MutationStage’
—
“scope” != ‘PerDiskMemtableFlushWriter_0’ AND “scope” != ‘GossipStage’) AND time >= ‘2021-07-10 00:00:00’ and time <= ‘2021-07-10 23:59:59’ GROUP BY time(30m), “scope”, “host”
2 * 24h = 48 row
- Query 04 – 1h/1d 단위
SELECT mean(“ActiveTasks_Value”) FROM “cassandra_ThreadPools” WHERE (“scope” != ‘Native-Transport-Requests’ AND “scope” != ‘MutationStage’
—
“scope” != ‘PerDiskMemtableFlushWriter_0’ AND “scope” != ‘GossipStage’) AND time >= ‘2021-07-10 00:00:00’ and time <= ‘2021-07-10 23:59:59’ GROUP BY time(1h), “scope”, “host”
1 * 24h = 24 row
[4] 분석 결과 및 결론
쿼리에서 뽑아낸 데이터의 row 개수와 쿼리문의 런타임간의 상관관계를 그래프화하여 한 눈에 성능 차이를 비교할 수 있도록 하였다.
row 개수와 total_time 의 상관관계
1) total_time = execution_time + planning_time
지정된 SELECT문을 EXPLAIN ANALYZE 한 값의 지표.
- EXPLAIN ANALYZE : 쿼리문의 런타임동안 성능 및 스토리지 분석
> execution_time : 쿼리를 실행하는 데 걸린 시간
> planning_time : 쿼리를 계획하는 데 걸린 시간
> total_time = execution_time + planning_time
2) 성능 최적화를 위한 최선의 구간 제시
group by time(2m) 의 효율이 가장 좋지만, group by time(5m) 가 성능 최적화를 위해서는 최선의 선택이다
> 전자는 query문 total_time이 21.xxx s로 로딩 시간이 긴 것이 문제.
> 후자는 query문 total_time이 9.xxx s로 10s 이내로 진입하며, row 개수도 급격하게 줄어드는 2가지 조건에 부합하는 가장 적절한 예시
결론
데이터베이스 튜닝의 여러 요소 중 SQL 문장을 튜닝하여, 데이터베이스 성능을 효율화하였다. 데이터베이스 자체의 하드웨어/소프트웨어 자원, 데이터베이스 자체의 설계, 개발/운영 단계에서 SQL 문장 튜닝 등 시스템 개발 중 여러 단계에서 튜닝을 고려하여 적절한 최적화 방법을 선택하여 최대의 효과를 내는 것이 중요하다. 갈수록 복잡화, 대량화되고 있는 데이터베이스 시스템을 운용하며, 여러가지 성능 관련 요소들을 분석함으로써 시스템을 최적화하고 안정화시키는 노력을 할 필요가 있다.
참조
https://dataonair.or.kr/db-tech-reference/d-lounge/report/?mod=document&uid=239679