Spanner는 쿼리, 읽기, 트랜잭션에 대한 유용한 정보를 얻는 데 도움이 되는 기본 제공 통계 테이블 집합을 제공합니다. 통계와 애플리케이션 코드의 상관관계를 파악하고 문제 해결을 개선하기 위해 애플리케이션 코드에서 Spanner 읽기, 쿼리, 트랜잭션 작업에 태그(자유 형식 문자열)를 추가할 수 있습니다. 이 태그는 통계 테이블에 채워지므로 태그를 기반으로 상관관계를 파악하고 검색할 수 있습니다.
Spanner는 두 가지 유형의 태그, 즉 요청 태그와 트랜잭션 태그를 지원합니다. 이름에서 알 수 있듯이 트랜잭션 태그를 트랜잭션에 추가하고 요청 태그를 개별 쿼리 및 읽기 API에 추가할 수 있습니다. 트랜잭션 범위에서 트랜잭션 태그를 설정하고 트랜잭션 내에서 적용 가능한 각 API 요청에 개별 요청 태그를 설정할 수 있습니다. 애플리케이션 코드에 설정된 요청 태그 및 트랜잭션 태그는 다음 통계 테이블의 열에 채워집니다.
통계표 | 통계표에 채워진 태그 유형 |
---|---|
TopN 쿼리 통계 | 요청 태그 |
TopN 읽기 통계 | 요청 태그 |
TopN 트랜잭션 통계 | 트랜잭션 태그 |
TopN 잠금 통계 | 트랜잭션 태그 |
요청 태그
쿼리 또는 읽기 요청에 선택적 요청 태그를 추가할 수 있습니다. Spanner는 요청 태그별로 통계를 그룹화합니다. 요청 태그는 쿼리 통계 및 읽기 통계 테이블의 REQUEST_TAG
필드에 표시됩니다.
요청 태그를 사용해야 하는 경우
다음은 요청 태그를 사용함으로써 이점을 얻을 수 있는 몇 가지 시나리오입니다.
- 문제가 있는 쿼리 또는 읽기의 소스 찾기: Spanner는 기본 제공 통계 테이블에서 읽기 및 쿼리에 대한 통계를 수집합니다. 통계 테이블에서 느린 쿼리 또는 CPU 사용량이 많은 읽기가 발견되면 이미 태그를 할당한 경우 태그에 포함된 정보를 기준으로 이러한 작업을 호출하는 소스(애플리케이션/마이크로서비스)를 식별할 수 있습니다.
- 통계 테이블에서 읽기 또는 쿼리 식별: 요청 태그를 할당하면 관심 있는 태그를 기준으로 통계 테이블의 행을 필터링할 수 있습니다.
- 특정 애플리케이션 또는 마이크로서비스의 쿼리 속도가 느린지 확인: 요청 태그를 사용하면 특정 애플리케이션 또는 마이크로서비스의 쿼리 지연 시간이 높은지 식별할 수 있습니다.
- 읽기 또는 쿼리 집합에 대한 통계 그룹화: 요청 태그를 사용하여 유사한 읽기 또는 쿼리 집합의 성능을 추적, 비교, 보고할 수 있습니다. 예를 들어 여러 쿼리가 동일한 액세스 패턴으로 테이블 또는 테이블 집합에 액세스하는 경우 모든 쿼리에 동일한 태그를 추가하여 함께 추적하는 것을 고려할 수 있습니다.
요청 태그를 할당하는 방법
다음 샘플은 Spanner 클라이언트 라이브러리를 사용하여 요청 태그를 설정하는 방법을 보여 줍니다.
C++
C#
Go
자바
Node.js
PHP
Python
Ruby
통계 테이블에서 요청 태그를 보는 방법
다음 쿼리는 10분 간격 동안 쿼리 통계를 반환합니다.
SELECT t.text,
t.request_tag,
t.execution_count,
t.avg_latency_seconds,
t.avg_rows,
t.avg_bytes
FROM SPANNER_SYS.QUERY_STATS_TOP_10MINUTE AS t
LIMIT 3;
쿼리에서 반환되는 결과의 예시로 다음 데이터를 살펴보겠습니다.
text | request_tag | execution_count | avg_latency_seconds | avg_rows | avg_bytes |
---|---|---|---|---|---|
SELECT SingerId, AlbumId, AlbumTitle FROM Albums | app=concert,env=dev,action=select | 212 | 0.025 | 21 | 2365 |
select * from orders; | app=catalogsearch,env=dev,action=list | 55 | 0.02 | 16 | 33.35 |
SELECT SingerId, FirstName, LastName FROM Singers; | [empty string] | 154 | 0.048 | 42 | 486.33 |
이 결과 테이블에서 쿼리에 REQUEST_TAG
를 할당하면 통계 테이블에 태그가 채워지는 것을 확인할 수 있습니다. 요청 태그가 할당되지 않은 경우 빈 문자열로 표시됩니다.
태그가 지정된 쿼리의 경우 태그별로 통계가 집계됩니다(예: 요청 태그 app=concert,env=dev,action=select
의 평균 지연 시간은 0.025초임). 할당된 태그가 없으면 쿼리별로 통계가 집계됩니다(예: 세 번째 행에 있는 쿼리의 평균 지연 시간은 0.048초임).
트랜잭션 태그
선택사항인 트랜잭션 태그를 개별 트랜잭션에 추가할 수 있습니다.
Spanner는 트랜잭션 통계 테이블의 TRANSACTION_TAG
필드에 표시되는 트랜잭션 태그별로 통계를 그룹화합니다.
트랜잭션 태그를 사용해야 하는 경우
다음은 트랜잭션 태그를 사용함으로써 이점을 얻을 수 있는 몇 가지 시나리오입니다.
- 문제가 있는 트랜잭션의 소스 찾기: Spanner는 트랜잭션 통계 테이블에서 읽기-쓰기 트랜잭션에 대한 통계를 수집합니다. 트랜잭션 통계 테이블에서 느린 트랜잭션이 발견되면 이미 태그를 할당한 경우 태그에 포함된 정보를 기준으로 이러한 트랜잭션을 호출하는 소스(애플리케이션/마이크로서비스)를 식별할 수 있습니다.
- 통계 테이블에서 트랜잭션 식별: 트랜잭션 태그를 할당하면 관심 있는 태그를 기준으로 트랜잭션 통계 테이블의 행을 필터링할 수 있습니다. 트랜잭션 태그가 없으면 통계가 나타내는 작업을 찾는 작업이 번거로울 수 있습니다. 예를 들어 트랜잭션 통계의 경우 태그가 지정되지 않은 트랜잭션을 식별하기 위해 관련 테이블과 열을 검사해야 합니다.
- 특정 애플리케이션 또는 마이크로서비스의 트랜잭션이 느린지 확인: 트랜잭션 태그를 사용하면 특정 애플리케이션 또는 마이크로서비스의 트랜잭션 지연 시간이 높은지 식별할 수 있습니다.
- 트랜잭션 집합에 대한 통계 그룹화: 트랜잭션 태그를 사용하여 유사한 트랜잭션 집합의 성능을 추적, 비교, 보고할 수 있습니다.
- 잠금 충돌과 관련된 열에 액세스하는 트랜잭션 찾기: 트랜잭션 태그를 사용하면 잠금 통계 테이블에서 잠금 충돌을 유발하는 개별 트랜잭션을 정확히 찾아낼 수 있습니다.
- 변경 내역을 사용해서 Spanner 외부로 사용자 변경 데이터 스트리밍: 변경 내역 데이터 레코드에는 사용자 데이터를 수정한 트랜잭션의 트랜잭션 태그가 포함됩니다. 그러면 변경 내역 리더가 태그를 기준으로 변경사항을 트랜잭션 유형과 연결할 수 있습니다.
트랜잭션 태그 할당 방법
다음 샘플은 Spanner 클라이언트 라이브러리를 사용하여 트랜잭션 태그를 설정하는 방법을 보여줍니다. 클라이언트 라이브러리를 사용할 때 트랜잭션 호출 시작 시 트랜잭션 태그를 설정하여 해당 트랜잭션 내의 모든 개별 작업에 적용할 수 있습니다.
C++
C#
Go
자바
Node.js
PHP
Python
Ruby
트랜잭션 통계 테이블에서 트랜잭션 태그를 보는 방법
다음 쿼리는 10분 간격 동안 트랜잭션 통계를 반환합니다.
SELECT t.fprint,
t.transaction_tag,
t.read_columns,
t.commit_attempt_count,
t.avg_total_latency_seconds
FROM SPANNER_SYS.TXN_STATS_TOP_10MINUTE AS t
LIMIT 3;
쿼리에서 반환되는 결과의 예시로 다음 데이터를 살펴보겠습니다.
fprint | transaction_tag | read_columns | commit_attempt_count | avg_total_latency_seconds |
---|---|---|---|---|
40015598317 | app=concert,env=dev | [Venues._exists, Venues.VenueId, Venues.VenueName, Venues.Capacity] |
278802 | 0.3508 |
20524969030 | app=product,service=payment | [Singers.SingerInfo] | 129012 | 0.0142 |
77848338483 | [empty string] | [Singers.FirstName, Singers.LastName, Singers._exists] | 5357 | 0.048 |
이 결과 테이블에서 트랜잭션에 TRANSACTION_TAG
를 할당하면 트랜잭션 통계 테이블에 태그가 채워지는 것을 확인할 수 있습니다. 트랜잭션 태그가 할당되지 않은 경우 빈 문자열로 표시됩니다.
태그가 지정된 트랜잭션의 경우 트랜잭션 태그별로 통계가 집계됩니다(예: 트랜잭션 태그 app=concert,env=dev
의 평균 지연 시간은 0.3508초임). 할당된 태그가 없으면 FPRINT
별로 통계가 집계됩니다 (예: 세 번째 행에 있는 77848338483의 평균 지연 시간은 0.048초임).
잠금 통계 테이블에서 트랜잭션 태그를 보는 방법
다음 쿼리는 10분 간격 동안 잠금 통계를 반환합니다.
CAST()
함수는 row_range_start_key
BYTES 필드를 STRING으로 변환합니다.
SELECT
CAST(s.row_range_start_key AS STRING) AS row_range_start_key,
s.lock_wait_seconds,
s.sample_lock_requests
FROM SPANNER_SYS.LOCK_STATS_TOP_10MINUTE s
LIMIT 2;
쿼리에서 반환되는 결과의 예시로 다음 데이터를 살펴보겠습니다.
row_range_start_key | lock_wait_seconds | sample_lock_requests |
---|---|---|
Songs(2,1,1) | 0.61 | LOCK_MODE: ReaderShared COLUMN: Singers.SingerInfo TRANSACTION_TAG: app=product,service=shipping LOCK_MODE: WriterShared COLUMN: Singers.SingerInfo TRANSACTION_TAG: app=product,service=payment |
albums(2,1+) | 0.48 | LOCK_MODE: ReaderShared COLUMN: users._exists1 TRANSACTION_TAG: [empty string] LOCK_MODE: WriterShared COLUMN: users._exists TRANSACTION_TAG: [empty string] |
이 결과 테이블에서 트랜잭션에 TRANSACTION_TAG
를 할당하면 잠금 통계 테이블에 태그가 채워지는 것을 확인할 수 있습니다. 트랜잭션 태그가 할당되지 않은 경우 빈 문자열로 표시됩니다.
API 메서드와 요청/트랜잭션 태그 간의 매핑
요청 태그와 트랜잭션 태그는 트랜잭션 모드가 읽기 전용 트랜잭션인지 읽기-쓰기 트랜잭션인지에 따라 특정 API 메서드에 적용될 수 있습니다. 일반적으로 트랜잭션 태그는 읽기-쓰기 트랜잭션에 적용되며 요청 태그는 읽기 전용 트랜잭션에 적용됩니다. 다음 표는 API 메서드에서 적용 가능한 태그 유형으로의 매핑을 보여줍니다.
API 메서드 | 트랜잭션 모드 | 요청 태그 | 트랜잭션 태그 |
---|---|---|---|
읽기, StreamingRead |
읽기 전용 트랜잭션 | 예 | 아니요 |
읽기-쓰기 트랜잭션 | 예 | 예 | |
ExecuteSql, ExecuteStreamingSql1 |
읽기 전용 트랜잭션1 | 예1 | 아니요 |
읽기-쓰기 트랜잭션 | 예 | 예 | |
ExecuteBatchDml | 읽기-쓰기 트랜잭션 | 예 | 예 |
BeginTransaction | 읽기-쓰기 트랜잭션 | 아니요 | 예 |
커밋 | 읽기-쓰기 트랜잭션 | 아니요 | 예 |
1 Apache Beam SpannerIO Dataflow 커넥터를 사용하여 실행되는 변경 스트림 쿼리의 경우 REQUEST_TAG
에 Dataflow 작업 이름이 포함됩니다.
제한사항
읽기, 쿼리, 트랜잭션에 태그를 추가할 때는 다음 제한사항을 고려하세요.
- 태그 문자열의 길이는 50자로 제한됩니다. 이 제한을 초과하는 문자열은 잘립니다.
- ASCII 문자(32~126)만 태그에 허용됩니다. 임의의 유니코드 문자는 밑줄로 대체됩니다.
- 모든 선행 밑줄(_)은 문자열에서 삭제됩니다.
- 태그는 대소문자를 구분합니다. 예를 들어 요청 태그
APP=cart,ENV=dev
를 하나의 쿼리 집합에 추가하고app=cart,env=dev
를 다른 쿼리 집합에 추가하면 Spanner는 각 태그에 대한 통계를 개별적으로 집계합니다. 다음과 같은 경우 통계 테이블에서 태그가 누락될 수 있습니다.
- Spanner가 특정 간격 동안 실행된 태그가 지정된 모든 작업에 대한 통계를 테이블에 저장할 수 없는 경우 시스템은 지정된 간격 동안 리소스 사용량이 가장 높은 작업부터 우선 저장합니다.
태그 이름 지정
데이터베이스 작업에 태그를 할당할 때 각 태그 문자열에 전달할 정보를 고려하는 것이 중요합니다. 선택한 규칙 또는 패턴을 사용하면 태그가 더 효과적입니다. 예를 들어 태그 이름을 올바르게 지정하면 통계와 애플리케이션 코드와 상관관계를 파악할 수 있습니다.
명시된 제한사항 내에서 원하는 태그를 선택할 수 있습니다. 하지만 태그 문자열을 쉼표로 구분된 키-값 쌍 집합으로 구성하는 것이 좋습니다.
예를 들어 전자상거래 사용 사례에 Spanner 데이터베이스를 사용한다고 가정해 보겠습니다. 특정 쿼리에 할당할 요청 태그에 애플리케이션, 개발 환경, 쿼리에서 수행하는 작업에 대한 정보를 포함할 수 있습니다. 키-값 형식의 태그 문자열을 app=cart,env=dev,action=update
로 할당할 수 있습니다. 즉, 쿼리는 개발 환경의 장바구니 애플리케이션에서 호출되며 장바구니를 업데이트하는 데 사용됩니다.
카탈로그 검색 애플리케이션에서 다른 쿼리가 있고 태그 문자열을 app=catalogsearch,env=dev,action=list
로 할당한다고 가정해 보겠습니다. 이제 이러한 쿼리 중 하나라도 쿼리 통계 테이블에 대기 시간이 긴 쿼리로 표시되면 태그를 사용하여 소스를 쉽게 식별할 수 있습니다.
다음은 태그 패턴을 사용하여 작업 통계를 구성하는 방법의 몇 가지 예시입니다. 이 예시는 모든 내용을 다루지 않습니다. 쉼표와 같은 구분 기호를 사용하여 태그 문자열에 결합할 수도 있습니다.
태그 키 | 태그-값 쌍 예시 | 설명 |
---|---|---|
애플리케이션 | app=cart app=frontend app=catalogsearch |
작업을 호출하는 애플리케이션을 식별하는 데 도움이 됩니다. |
환경 | env=prod env=dev env=test env=staging |
작업과 연결된 환경을 식별하는 데 도움이 됩니다. |
프레임워크 | framework=spring framework=django framework=jetty |
작업과 연결된 프레임워크를 식별하는 데 도움이 됩니다. |
작업 | action=list action=retrieve action=update |
작업에 의해 수행된 작업을 식별하는 데 도움이 됩니다. |
서비스 | service=payment service=shipping |
작업을 호출하는 마이크로서비스를 식별하는 데 도움이 됩니다. |
다음에 주목하세요.
REQUEST_TAG
를 할당하면 태그 문자열이 동일한 여러 쿼리의 통계가 쿼리 통계 테이블의 단일 행에 그룹화됩니다. 이러한 쿼리 중 하나의 텍스트만TEXT
필드에 표시됩니다.REQUEST_TAG
를 할당하면 태그 문자열이 동일한 여러 읽기의 통계가 읽기 통계 테이블의 단일 행으로 그룹화됩니다. 읽은 모든 열 집합이READ_COLUMNS
필드에 추가됩니다.TRANSACTION_TAG
를 할당하면 태그 문자열이 동일한 트랜잭션의 통계가 트랜잭션 통계 테이블의 단일 행으로 그룹화됩니다. 트랜잭션으로 작성된 모든 열 집합이WRITE_CONSTRUCTIVE_COLUMNS
필드에 추가되고 읽은 모든 열 집합이READ_COLUMNS
필드에 추가됩니다.
태그를 사용한 문제 해결 시나리오
문제가 있는 트랜잭션의 소스 찾기
다음 쿼리는 선택한 기간 동안 상위 트랜잭션의 원시 데이터를 반환합니다.
SELECT
fprint,
transaction_tag,
ROUND(avg_total_latency_seconds,4) as avg_total_latency_sec,
ROUND(avg_commit_latency_seconds,4) as avg_commit_latency_sec,
commit_attempt_count,
commit_abort_count
FROM SPANNER_SYS.TXN_STATS_TOP_10MINUTE
WHERE interval_end = "2020-05-17T18:40:00"
ORDER BY avg_total_latency_seconds DESC;
다음 표에는 쿼리에서 반환된 데이터의 예시가 나와 있습니다. 여기에는 동일한 데이터베이스를 소유하거나 쿼리하는 세 개의 애플리케이션, 즉 장바구니, 제품, 프런트엔드가 있습니다.
지연 시간이 긴 트랜잭션을 식별하면 관련 태그를 사용하여 애플리케이션 코드의 관련 부분을 식별하고 트랜잭션 통계를 사용하여 추가 문제를 해결할 수 있습니다.
fprint | transaction_tag | avg_total_latency_sec | avg_commit_latency_sec | commit_attempt_count | commit_abort_count |
---|---|---|---|---|---|
7129109266372596045 | app=cart,service=order | 0.3508 | 0.0139 | 278802 | 142205 |
9353100217060788102 | app=cart,service=redis | 0.1633 | 0.0142 | 129012 | 27177 |
9353100217060788102 | app=product,service=payment | 0.1423 | 0.0133 | 5357 | 636 |
898069986622520747 | app=product,service=shipping | 0.0159 | 0.0118 | 4269 | 1 |
9521689070912159706 | app=frontend,service=ads | 0.0093 | 0.0045 | 164 | 0 |
11079878968512225881 | [empty string] | 0.031 | 0.015 | 14 | 0 |
마찬가지로 요청 태그는 쿼리 통계 테이블에서 문제가 있는 쿼리의 소스와 읽기 통계 테이블에서 문제가 있는 읽기의 소스를 찾는 데 사용할 수 있습니다.
특정 애플리케이션 또는 마이크로서비스의 트랜잭션에 대한 지연 시간 및 기타 통계 찾기
태그 문자열에 애플리케이션 이름 또는 마이크로서비스 이름을 사용한 경우 해당 애플리케이션 이름 또는 마이크로서비스 이름이 포함된 태그로 트랜잭션 통계 테이블을 필터링할 수 있습니다.
결제 앱에 새 트랜잭션을 추가했고 새 트랜잭션의 지연 시간 및 기타 통계를 확인하려고 한다고 가정해 보겠습니다. 태그 내에서 결제 애플리케이션 이름을 사용한 경우 app=payment
가 포함된 태그에 대해서만 트랜잭션 통계 테이블을 필터링할 수 있습니다.
다음 쿼리는 10분 간격 동안 결제 앱의 트랜잭션 통계를 반환합니다.
SELECT
transaction_tag,
avg_total_latency_sec,
avg_commit_latency_sec,
commit_attempt_count,
commit_abort_count
FROM SPANNER_SYS.TXN_STATS_TOP_10MINUTE
WHERE STARTS_WITH(transaction_tag, "app=payment")
LIMIT 3;
출력 예시는 다음과 같습니다.
transaction_tag | avg_total_latency_sec | avg_commit_latency_sec | commit_attempt_count | commit_abort_count |
---|---|---|---|---|
app=payment,action=update | 0.3508 | 0.0139 | 278802 | 142205 |
app=payment,action=transfer | 0.1633 | 0.0142 | 129012 | 27177 |
app=payment, action=retrieve | 0.1423 | 0.0133 | 5357 | 636 |
마찬가지로 요청 태그를 사용하여 쿼리 통계 또는 읽기 통계 테이블에서 특정 애플리케이션의 쿼리 또는 읽기를 찾을 수 있습니다.
잠금 충돌과 관련된 트랜잭션 검색
잠금 대기 시간이 긴 트랜잭션과 row key를 확인하기 위해 잠금 충돌과 관련된 row key, 열, 해당 트랜잭션이 나열된 LOCK_STAT_TOP_10MINUTE
테이블을 쿼리합니다.
SELECT CAST(s.row_range_start_key AS STRING) AS row_range_start_key,
t.total_lock_wait_seconds,
s.lock_wait_seconds,
s.lock_wait_seconds/t.total_lock_wait_seconds frac_of_total,
s.sample_lock_requests
FROM spanner_sys.lock_stats_total_10minute t, spanner_sys.lock_stats_top_10minute s
WHERE
t.interval_end = "2020-05-17T18:40:00" and s.interval_end = t.interval_end;
쿼리의 출력 예시는 다음과 같습니다.
row_range_start_key | total_lock_wait_seconds | lock_wait_seconds | frac_of_total | sample_lock_requests |
---|---|---|---|---|
Singers(32) | 2.37 | 1.76 | 1 | LOCK_MODE: WriterShared COLUMN: Singers.SingerInfo TRANSACTION_TAG: app=cart,service=order LOCK_MODE: ReaderShared COLUMN: Singers.SingerInfo TRANSACTION_TAG: app=cart,service=redis |
이 결과 테이블에서 SingerId=32 키의 Singers
테이블에서 충돌이 발생한 것을 확인할 수 있습니다. Singers.SingerInfo
는 ReaderShared
와 WriterShared
사이에 잠금 충돌이 발생한 열입니다. 또한 충돌이 발생한 해당 트랜잭션(app=cart,service=order
및 app=cart,service=redis
)을 식별할 수 있습니다.
잠금 충돌을 유발하는 트랜잭션이 식별되면 이제 트랜잭션 통계를 사용하여 이러한 트랜잭션에 집중하여 트랜잭션이 수행하는 작업과 충돌을 방지하거나 잠금이 유지되는 시간을 줄일 수 있는지 파악할 수 있습니다. 자세한 내용은 잠금 경합을 줄이기 위한 권장사항을 참조하세요.
다음 단계
- 다른 점검 도구 알아보기
- Spanner가 각 데이터베이스에 대해 데이터베이스의 정보 스키마 테이블에 저장하는 다른 정보 알아보기
- Spanner 관련 SQL 권장사항 자세히 알아보기
- 높은 CPU 사용률 조사 자세히 알아보기