Spanner는 읽기에 대한 통계를 저장하는 기본 제공 테이블을 제공합니다. SQL 문을 사용하여 이러한 SPANNER_SYS.READ_STATS*
테이블에서 통계를 검색할 수 있습니다.
읽기 통계를 사용해야 하는 경우
읽기 통계는 애플리케이션이 데이터베이스를 사용하는 방식에 대한 통계를 제공하며 성능 문제를 조사할 때 유용합니다. 예를 들어 데이터베이스에 대해 어떤 읽기 유형이 실행되는지, 실행 빈도가 어떤지, 이러한 읽기 유형의 성능 특성이 어떤지를 확인할 수 있습니다. 데이터베이스의 읽기 통계를 사용하여 CPU 사용량이 높은 읽기 유형을 식별할 수 있습니다. 상위 수준에서 읽기 통계는 리소스 사용량 측면에서 데이터베이스로 이동하는 트래픽의 동작을 이해하는 데 도움이 됩니다.
제한사항
이 도구는 CPU 사용률의 대부분을 차지하는 유사한 읽기 스트림을 분석하는 데 가장 적합합니다. 한 번만 실행된 읽기는 검색하지 않는 것이 좋습니다.
이 통계에서 추적하는 CPU 사용량은 프리페치 CPU 사용량과 기타 오버헤드를 제외한 Spanner 서버 측 CPU 사용량을 나타냅니다.
통계는 최선의 방식으로 수집됩니다. 따라서 기본 시스템에 문제가 있으면 통계가 누락될 수 있습니다. 예를 들어 내부 네트워킹 문제가 있으면 일부 통계가 누락될 수 있습니다.
사용 가능 여부
SPANNER_SYS
데이터는 SQL 인터페이스를 통해서만 사용할 수 있습니다. 예를 들면 다음과 같습니다.
Google Cloud 콘솔에 있는 데이터베이스의 Spanner 스튜디오 페이지
gcloud spanner databases execute-sql
명령어executeQuery
API
Spanner가 제공하는 다른 단일 읽기 메서드는 SPANNER_SYS
를 지원하지 않습니다.
읽기 유형별로 그룹화된 CPU 사용량
다음 테이블은 특정 기간 동안 CPU 사용량이 가장 높은 읽기 유형을 추적합니다.
SPANNER_SYS.READ_STATS_TOP_MINUTE
: 1분 간격으로 집계된 읽기 유형SPANNER_SYS.READ_STATS_TOP_10MINUTE
: 10분 간격으로 집계된 읽기 유형SPANNER_SYS.READ_STATS_TOP_HOUR
: 1시간 간격으로 집계된 읽기 유형
이러한 테이블에는 다음과 같은 속성이 있습니다.
각 테이블에는 테이블 이름에 지정된 길이의 겹치지 않는 시간 간격에 대한 데이터가 포함되어 있습니다.
간격은 시계 시간을 기준으로 합니다. 1분 간격은 매분 정각에 끝나고 10분 간격은 매시 정각에 시작해서 10분 단위로 끝나며 1시간 간격은 매시 정각에 끝납니다. 각 간격이 끝날 때마다 Spanner는 모든 서버에서 데이터를 수집한 다음 곧 SPANNER_SYS 테이블에 데이터를 제공합니다.
예를 들어 오전 11:59:30에 SQL 쿼리에 사용할 수 있는 가장 최근 간격은 다음과 같습니다.
- 1분: 오전 11:58:00–11:58:59
- 10분: 오전 11:40:00–11:49:59
- 1시간: 오전 10:00:00~10:59:59
Spanner는 읽기 유형별로 통계를 그룹화합니다. 태그가 있으면 FPRINT는 태그의 해시입니다. 그렇지 않은 경우
READ_COLUMNS
값의 해시입니다.각 행에는 Spanner가 지정된 간격 동안 통계를 캡처하는 특정 읽기 유형의 모든 실행에 대한 통계가 포함됩니다.
Spanner가 특정 간격 동안 실행된 모든 개별 읽기 유형에 대한 정보를 저장할 수 없는 경우 시스템은 지정된 간격 동안 CPU 사용량이 가장 높은 읽기 유형부터 우선 저장됩니다.
테이블 스키마
열 이름 | 유형 | 설명 |
---|---|---|
INTERVAL_END |
TIMESTAMP |
포함된 읽기 실행이 발생한 시간 간격의 끝입니다. |
REQUEST_TAG |
STRING |
이 읽기 작업의 요청 태그입니다(선택사항). 태그 사용에 대한 자세한 내용은 요청 태그 문제해결을 참조하세요. 태그 문자열이 동일한 여러 읽기의 통계는 해당 태그 문자열과 일치하는 'REQUEST_TAG'와 함께 단일 행으로 그룹화됩니다. |
READ_TYPE |
STRING |
읽기가 PARTITIONED_READ 또는 READ 인지 여부를 나타냅니다. PartitionRead API에서 가져온 partitionToken을 사용한 읽기는 PARTITIONED_READ 읽기 유형으로 표시되고 다른 읽기 API는 READ 로 표시됩니다.
|
READ_COLUMNS |
ARRAY<STRING> |
읽은 열의 집합입니다. 알파벳순으로 나열됩니다. |
FPRINT |
INT64 |
REQUEST_TAG 값의 해시가 있는 경우입니다. 그렇지 않으면 READ_COLUMNS 값의 해시입니다. |
EXECUTION_COUNT |
INT64 |
해당 간격 동안 Spanner가 읽기 유형을 실행한 횟수입니다. |
AVG_ROWS |
FLOAT64 |
읽기가 반환한 평균 행 수입니다. |
AVG_BYTES |
FLOAT64 |
읽기에서 반환된 평균 데이터 바이트 수입니다(전송 인코딩 오버헤드 제외). |
AVG_CPU_SECONDS |
FLOAT64 |
프리페치 CPU 및 기타 오버헤드를 제외하고 읽기를 실행하는 Spanner 서버 측 평균 CPU 초입니다. |
AVG_LOCKING_DELAY_SECONDS |
FLOAT64 |
잠금으로 인해 대기에 소비한 평균 시간(초)입니다. |
AVG_CLIENT_WAIT_SECONDS |
FLOAT64 |
클라이언트가 Spanner에서 생성하는 만큼 빠르게 데이터를 소비하지 않기 때문에 대기한 평균 시간(초)입니다. |
AVG_LEADER_REFRESH_DELAY_SECONDS |
FLOAT64 |
모든 쓰기가 관측되었고 Paxos 리더가 확인하기 위해 대기한 평균 시간(초)입니다. |
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT |
INT64 |
읽기-쓰기 트랜잭션의 일부로 읽기가 실행된 횟수입니다. 이 열을 사용하면 읽기를 읽기 전용 트랜잭션으로 이동하여 잠금 경합을 방지할 수 있는지 확인할 수 있습니다. |
쿼리 예
이 섹션에는 읽기 통계를 검색하는 SQL 문의 몇 가지 예시가 포함되어 있습니다. 이러한 SQL 문은 클라이언트 라이브러리, gcloud spanner 또는 Google Cloud Console을 사용하여 실행할 수 있습니다.
일정 기간 동안의 각 읽기 유형의 기본 통계 나열
다음 쿼리는 가장 최근 1분 시간 간격 내 최상위 읽기 유형의 원시 데이터를 반환합니다.
SELECT fprint,
read_columns,
execution_count,
avg_cpu_seconds,
avg_rows,
avg_bytes,
avg_locking_delay_seconds,
avg_client_wait_seconds
FROM spanner_sys.read_stats_top_minute
ORDER BY interval_end DESC LIMIT 3;
쿼리 출력
fprint | read_columns | execution_count | avg_cpu_seconds | avg_rows | avg_bytes | avg_locking_delay_seconds | avg_client_wait_seconds |
---|---|---|---|---|---|---|---|
125062082139 |
["Singers.id", "Singers.name"] |
8514387 |
0.000661355290396507 |
310.79 |
205 |
8.3232564943763752e-06 |
0 |
151238888745 |
["Singers.singerinfo"] |
3341542 |
6.5992827184280315e-05 |
12784 |
54 |
4.6859741349028595e-07 |
0 |
14105484 |
["Albums.id", "Albums.title"] |
9306619 |
0.00017855774721667873 |
1165.4 |
2964.71875 |
1.4328191393074178e-06 |
0 |
읽기 유형을 나열하여 총 CPU 사용량을 기준으로 정렬
다음 쿼리는 최근 1시간 동안 CPU 사용량이 가장 높은 읽기 유형을 반환합니다.
SELECT read_columns,
execution_count,
avg_cpu_seconds,
execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.read_stats_top_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.read_stats_top_hour)
ORDER BY total_cpu DESC LIMIT 3;
쿼리 출력
read_columns | execution_count | avg_cpu_seconds | total_cpu |
---|---|---|---|
["Singers.id", "Singers.name"] |
1647 |
0.00023380297430622681 |
0.2579 |
["Albums.id", "Albums.title"] |
720 |
0.00016738889440282034 |
0.221314999999999 |
["Singers.singerinfo""] |
3223 |
0.00037764625882302246 |
0.188053 |
집계 통계
SPANNER_SYS
에는 특정 기간 동안 Spanner에서 캡처한 집계 읽기 통계를 저장하는 테이블도 포함됩니다.
SPANNER_SYS.READ_STATS_TOTAL_MINUTE
: 1분 간격 내 모든 읽기 유형의 집계 통계SPANNER_SYS.READ_STATS_TOTAL_10MINUTE
: 10분 간격 내 모든 읽기 유형의 집계 통계SPANNER_SYS.READ_STATS_TOTAL_HOUR
: 1시간 간격 내 모든 읽기 유형의 집계 통계
집계 통계 테이블에는 다음과 같은 속성이 있습니다.
각 테이블에는 테이블 이름에 지정된 길이의 겹치지 않는 시간 간격에 대한 데이터가 포함되어 있습니다.
간격은 시계 시간을 기준으로 합니다. 1분 간격은 매분 정각에 끝나고, 10분 간격은 매시 정각에 시작해서 10분 단위로 끝나며, 1시간 간격은 매시 정각에 끝납니다.
예를 들어 오전 11:59:30에 집계 읽기 통계에서 SQL 쿼리에 사용할 수 있는 가장 최근 간격은 다음과 같습니다.
- 1분: 오전 11:58:00–11:58:59
- 10분: 오전 11:40:00–11:49:59
- 1시간: 오전 10:00:00~10:59:59
각 행에는 지정된 간격 동안 데이터베이스에 대해 실행된 모든 읽기 유형에 대한 통계가 함께 집계됩니다. 따라서 시간 간격당 하나의 행만 있습니다.
SPANNER_SYS.READ_STATS_TOTAL_*
테이블에 캡처된 통계에는 Spanner가SPANNER_SYS.READ_STATS_TOP_*
테이블에 캡처하지 않은 읽기 유형이 포함될 수 있습니다.이러한 테이블의 일부 열은 Cloud Monitoring에서 측정항목으로 노출됩니다. 노출된 측정항목은 다음과 같습니다.
- 반환된 행 수
- 읽기 실행 횟수
- 읽기 CPU 시간
- 잠금 지연
- 클라이언트 대기 시간
- 리더 새로고침 지연
- 반환된 바이트 수
자세한 내용은 Spanner 측정항목을 참조하세요.
테이블 스키마
열 이름 | 유형 | 설명 |
---|---|---|
INTERVAL_END |
TIMESTAMP |
포함된 읽기 유형 실행이 발생한 시간 간격의 끝입니다. |
EXECUTION_COUNT |
INT64 |
해당 간격 동안 Spanner가 읽기 유형을 실행한 횟수입니다. |
AVG_ROWS |
FLOAT64 |
읽기가 반환한 평균 행 수입니다. |
AVG_BYTES |
FLOAT64 |
읽기에서 반환된 평균 데이터 바이트 수입니다(전송 인코딩 오버헤드 제외). |
AVG_CPU_SECONDS |
FLOAT64 |
프리페치 CPU 및 기타 오버헤드를 제외하고 읽기를 실행하는 Spanner 서버 측 평균 CPU 초입니다. |
AVG_LOCKING_DELAY_SECONDS |
FLOAT64 |
잠금으로 인해 대기에 소비한 평균 시간(초)입니다. |
AVG_CLIENT_WAIT_SECONDS |
FLOAT64 |
제한으로 인해 대기에 소비한 평균 시간(초)입니다. |
AVG_LEADER_REFRESH_DELAY_SECONDS |
FLOAT64 |
멀티 리전 구성에서 인스턴스 간에 읽기를 조정하는 데 사용된 평균 시간(초)입니다. |
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT |
INT64 |
읽기-쓰기 트랜잭션의 일부로 읽기가 실행된 횟수입니다. 이 열을 사용하면 일부 읽기를 읽기 전용 트랜잭션으로 이동하여 잠금 경합을 방지할 수 있는지 확인할 수 있습니다. |
쿼리 예
이 섹션에는 집계 읽기 통계를 검색하는 SQL 문의 몇 가지 예시가 포함되어 있습니다. 이러한 SQL 문은 클라이언트 라이브러리, gcloud spanner 또는 Google Cloud Console을 사용하여 실행할 수 있습니다.
모든 읽기 유형에서 총 CPU 사용량 찾기
다음 쿼리는 최근 1시간 동안 읽기 유형에서 소비한 CPU 시간 수를 반환합니다.
SELECT (avg_cpu_seconds * execution_count / 60 / 60)
AS total_cpu_hours
FROM spanner_sys.read_stats_total_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.read_stats_total_hour);
쿼리 출력
total_cpu_hours |
---|
0.00026186111111111115 |
일정 기간 동안의 총 실행 횟수 확인
다음 쿼리는 가장 최근 1분 간격 내 실행된 총 읽기 유형의 수를 반환합니다.
SELECT interval_end,
execution_count
FROM spanner_sys.read_stats_total_minute
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.read_stats_total_minute);
쿼리 출력
interval_end | execution_count |
---|---|
2020-05-28 11:02:00-07:00 |
12861966 |
데이터 보관
Spanner는 각 테이블의 데이터를 최소한 다음 기간 동안 보관합니다.
SPANNER_SYS.READ_STATS_TOP_MINUTE
및SPANNER_SYS.READ_STATS_TOTAL_MINUTE
: 이전 6시간을 포함하는 간격SPANNER_SYS.READ_STATS_TOP_10MINUTE
및SPANNER_SYS.READ_STATS_TOTAL_10MINUTE
: 이전 4일을 포함하는 간격SPANNER_SYS.READ_STATS_TOP_HOUR
및SPANNER_SYS.READ_STATS_TOTAL_HOUR
: 이전 30일을 포함하는 간격
읽기 통계로 높은 CPU 사용량 문제 해결
Spanner 읽기 통계는 Spanner 데이터베이스에서 높은 CPU 사용량을 조사해야 하거나 데이터베이스에서 CPU 사용량이 많은 읽기 유형을 이해하려는 경우에 유용합니다. 대량의 데이터베이스 리소스를 사용하는 읽기 유형을 검사하면 Spanner 사용자는 운영 비용을 줄이고 일반적인 시스템 지연 시간을 개선할 수 있습니다. 다음 단계에서는 읽기 통계를 사용하여 데이터베이스에서 높은 CPU 사용량을 조사하는 방법을 보여줍니다.
조사 기간 선택
애플리케이션에서 CPU 사용량이 많을 때를 찾아 조사를 시작합니다. 예를 들어 다음 시나리오에서는 2020년 5월 28일 오후 5시 20분경에 문제가 발생하기 시작했습니다.
선택한 기간의 읽기 통계 수집
조사를 시작하는 기간을 선택했으므로 해당 시간 동안의 READ_STATS_TOTAL_10MINUTE
테이블에서 수집된 통계를 살펴봅니다.
이 쿼리의 결과를 통해 해당 기간 동안 CPU 및 기타 읽기 통계가 어떻게 변화했는지 알 수 있습니다. 다음 쿼리는 4:30 pm
부터 7:30 pm
(포함)까지의 집계 읽기 통계를 반환합니다.
SELECT
interval_end,
ROUND(avg_cpu_seconds,4) as avg_cpu_seconds,
execution_count,
avg_locking_delay_seconds
FROM SPANNER_SYS.READ_STATS_TOTAL_10MINUTE
WHERE
interval_end >= "2020-05-28T16:30:00"
AND interval_end <= "2020-05-28T19:30:00"
ORDER BY interval_end;
다음 데이터는 쿼리에서 반환되는 결과의 예시입니다.
interval_end | avg_cpu_seconds | execution_count | avg_locking_delay_seconds |
---|---|---|---|
2020-05-28 16:40:00-07:00 | 0.0004 | 11111421 | 8.3232564943763752e-06 |
2020-05-28 16:50:00-07:00 | 0.0002 | 8815637 | 8.98734051776406e-05 |
2020-05-28 17:00:00-07:00 | 0.0001 | 8260215 | 6.039129247846453e-06 |
2020-05-28 17:10:00-07:00 | 0.0001 | 8514387 | 9.0535466616680686e-07 |
2020-05-28 17:20:00-07:00 | 0.0006 | 13715466 | 2.6801485272173765e-06 |
2020-05-28 17:30:00-07:00 | 0.0007 | 12861966 | 4.6859741349028595e-07 |
2020-05-28 17:40:00-07:00 | 0.0007 | 3755954 | 2.7131391918005383e-06 |
2020-05-28 17:50:00-07:00 | 0.0006 | 4248137 | 1.4328191393074178e-06 |
2020-05-28 18:00:00-07:00 | 0.0006 | 3986198 | 2.6973481999639748e-06 |
2020-05-28 18:10:00-07:00 | 0.0006 | 3510249 | 3.7577083563017905e-06 |
2020-05-28 18:20:00-07:00 | 0.0004 | 3341542 | 4.0940589703795433e-07 |
2020-05-28 18:30:00-07:00 | 0.0002 | 8695147 | 1.9914494947583975e-05 |
2020-05-28 18:40:00-07:00 | 0.0003 | 11679702 | 1.8331461539001595e-05 |
2020-05-28 18:50:00-07:00 | 0.0003 | 9306619 | 1.2527332321222135e-05 |
2020-05-28 19:00:00-07:00 | 0.0002 | 8520508 | 6.2268448078447915e-06 |
2020-05-28 19:10:00-07:00 | 0.0006 | 13715466 | 2.6801485272173765e-06 |
2020-05-28 19:20:00-07:00 | 0.0005 | 11947323 | 3.3029114639321295e-05 |
2020-05-28 19:30:00-07:00 | 0.0002 | 8514387 | 9.0535466616680686e-07 |
여기에서 보면 평균 CPU 시간(avg_cpu_seconds
)이 더 높습니다(간격 강조표시). 값이 2020-05-28 19:20:00인 interval_end
의 CPU 시간이 더 높으므로 다음 단계에서 추가 조사를 위해 해당 간격을 선택하겠습니다.
높은 CPU 사용률을 유발하는 읽기 유형 찾기
좀 더 자세히 들어가서 이제 앞 단계에서 선택한 간격의 READ_STATS_TOP_10MINUTE
테이블을 쿼리합니다. 이 쿼리의 결과는 CPU 사용량이 많은 읽기 유형을 나타내는 데 도움이 됩니다.
SELECT
read_columns,
ROUND(avg_cpu_seconds,4) as avg_cpu_seconds,
execution_count,
avg_rows
FROM SPANNER_SYS.READ_STATS_TOP_10MINUTE
WHERE
interval_end = "2020-05-28T19:20:00"
ORDER BY avg_cpu_seconds DESC LIMIT 3;
다음 데이터는 쿼리에서 다시 반환되는 결과의 예시로서 avg_cpu_seconds
의 순위를 기준으로 상위 3개의 읽기 유형에 대한 정보를 반환합니다. 쿼리에서 ROUND
를 사용하여 avg_cpu_seconds
의 출력을 소수점 이하 4자리로 제한합니다.
read_columns | avg_cpu_seconds | execution_count | avg_rows |
---|---|---|---|
[TestHigherLatency._exists,TestHigherLatency.lang_status,TestHigherLatency.score,globalTagAffinity.shares] 1 |
0.4192 | 1182 | 11650.42216582 |
[TestHigherLatency._exists,TestHigherLatency.lang_status,TestHigherLatency.likes,globalTagAffinity.score] |
0.0852 | 4 | 12784 |
[TestHigherLatency._exists,TestHigherLatency.lang_status,TestHigherLatency.score,globalTagAffinity.ugcCount] |
0.0697 | 1140 | 310.7921052631 |
1 _exists
는 특정 행이 있는지 여부를 확인하는 데 사용되는 내부 필드입니다.
CPU 사용량이 높은 한 가지 이유는 몇 가지 읽기 유형을 더 자주 실행하기 때문입니다(execution_count
). 읽기가 반환한 평균 행 수가 증가했을 수도 있습니다(avg_rows
). 읽기 유형의 이러한 속성 중 하나라도 해당하는 것이 없는 경우 avg_locking_delay_seconds
, avg_client_wait_seconds
또는 avg_bytes
와 같은 다른 속성을 검사할 수 있습니다.
높은 CPU 사용량을 줄이기 위한 권장사항 적용
앞의 단계를 수행했다면 이 권장사항 중 어느 것이 상황에 도움이 될지 고려해 보세요.
지정된 간격 동안 Spanner가 읽기 유형을 실행한 횟수는 측정값이 합당한지 또는 문제의 징후를 나타내는지의 기준이 되는 측정 항목의 좋은 예입니다. 측정 항목의 기준을 설정하면 정상적인 동작 상의 예상치 못한 편차의 원인을 감지하고 조사할 수 있습니다.
CPU 사용량이 대부분의 경우 비교적 일정하게 진행되지만 갑자기 사용자 요청 또는 애플리케이션 동작의 급격한 증가가 있을 때 이와 관련하여 급격한 상승이 나타나고, 이는 모든 것이 예상대로 작동한다는 표지입니다.
다음 쿼리를 사용하여 각 읽기 유형에 대해 Spanner가 실행된 횟수별로 순위가 지정된 상위 읽기 유형을 찾습니다.
SELECT interval_end, read_columns, execution_count FROM SPANNER_SYS.READ_STATS_TOP_MINUTE ORDER BY execution_count DESC LIMIT 10;
특히 멀티 리전 인스턴스 구성을 사용할 때 가장 짧은 읽기 지연 시간을 찾고 있다면 강력한 읽기 대신 비활성 읽기를 사용하여
AVG_LEADER_REFRESH_DELAY_SECONDS
구성요소의 읽기 지연시간을 줄이거나 제거합니다.읽기만 수행하고 단일 읽기 메서드를 사용하여 읽기를 표현할 수 있는 경우, 해당 단일 읽기 메서드를 사용해야 합니다. 단일 읽기는 읽기-쓰기 트랜잭션과 달리 잠기지 않습니다. 따라서 데이터를 쓰지 않을 때는 비용이 많이 드는 읽기-쓰기 트랜잭션보다 읽기 전용 트랜잭션을 사용해야 합니다.
다음 단계
- 다른 점검 도구 알아보기
- Spanner가 각 데이터베이스에 대해 데이터베이스의 정보 스키마 테이블에 저장하는 다른 정보 알아보기
- Spanner 관련 SQL 권장사항에 대해 자세히 알아보기
- 높은 CPU 사용률 조사에 대해 자세히 알아보기