Spanner는 쿼리, 읽기, 트랜잭션에 대한 유용한 정보를 얻는 데 도움이 되는 기본 제공 통계 테이블 집합을 제공합니다. 통계와 애플리케이션 코드의 상관관계를 파악하고 문제 해결을 개선하기 위해 애플리케이션 코드에서 Spanner 읽기, 쿼리, 트랜잭션 작업에 태그(자유 형식 문자열)를 추가할 수 있습니다. 이 태그는 통계 테이블에 채워지므로 태그를 기반으로 상관관계를 파악하고 검색할 수 있습니다.
Spanner는 두 가지 유형의 태그, 즉 요청 태그와 트랜잭션 태그를 지원합니다. 이름에서 알 수 있듯이 트랜잭션 태그를 트랜잭션에 추가하고 요청 태그를 개별 쿼리 및 읽기 API에 추가할 수 있습니다. 트랜잭션 범위에서 트랜잭션 태그를 설정하고 트랜잭션 내에서 적용 가능한 각 API 요청에 개별 요청 태그를 설정할 수 있습니다. 애플리케이션 코드에 설정된 요청 태그 및 트랜잭션 태그는 다음 통계 테이블의 열에 채워집니다.
통계표 | 통계표에 채워진 태그 유형 |
---|---|
TopN 쿼리 통계 | 요청 태그 |
TopN 읽기 통계 | 요청 태그 |
TopN 트랜잭션 통계 | 트랜잭션 태그 |
TopN 잠금 통계 | 트랜잭션 태그 |
요청 태그
쿼리 또는 읽기 요청에 선택적 요청 태그를 추가할 수 있습니다. Spanner는 요청 태그별로 통계를 그룹화합니다. 요청 태그는 쿼리 통계 및 읽기 통계 테이블의 REQUEST_TAG
필드에 표시됩니다.
요청 태그를 사용해야 하는 경우
다음은 요청 태그를 사용함으로써 이점을 얻을 수 있는 몇 가지 시나리오입니다.
- 문제가 있는 쿼리 또는 읽기의 소스 찾기: Spanner는 기본 제공 통계 테이블에서 읽기 및 쿼리에 대한 통계를 수집합니다. 통계 테이블에서 느린 쿼리 또는 CPU 사용량이 많은 읽기가 발견되면 이미 태그를 할당한 경우 태그에 포함된 정보를 기준으로 이러한 작업을 호출하는 소스(애플리케이션/마이크로서비스)를 식별할 수 있습니다.
- 통계 테이블에서 읽기 또는 쿼리 식별: 요청 태그를 할당하면 관심 있는 태그를 기준으로 통계 테이블의 행을 필터링할 수 있습니다.
- 특정 애플리케이션 또는 마이크로서비스의 쿼리 속도가 느린지 확인: 요청 태그를 사용하면 특정 애플리케이션 또는 마이크로서비스의 쿼리 지연 시간이 높은지 식별할 수 있습니다.
- 읽기 또는 쿼리 집합에 대한 통계 그룹화: 요청 태그를 사용하여 유사한 읽기 또는 쿼리 집합의 성능을 추적, 비교, 보고할 수 있습니다. 예를 들어 여러 쿼리가 동일한 액세스 패턴으로 테이블 또는 테이블 집합에 액세스하는 경우 모든 쿼리에 동일한 태그를 추가하여 함께 추적하는 것을 고려할 수 있습니다.
요청 태그를 할당하는 방법
다음 샘플은 Spanner 클라이언트 라이브러리를 사용하여 요청 태그를 설정하는 방법을 보여 줍니다.
통계 테이블에서 요청 태그를 보는 방법
다음 쿼리는 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 클라이언트 라이브러리를 사용하여 트랜잭션 태그를 설정하는 방법을 보여줍니다. 클라이언트 라이브러리를 사용할 때 트랜잭션 호출 시작 시 트랜잭션 태그를 설정하여 해당 트랜잭션 내의 모든 개별 작업에 적용할 수 있습니다.
트랜잭션 통계 테이블에서 트랜잭션 태그를 보는 방법
다음 쿼리는 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 사용률 조사 자세히 알아보기