이 페이지에서는 데이터베이스의 핫스팟을 인식하고 디버그하는 방법을 설명합니다. GoogleSQL과 PostgreSQL 모두를 사용하여 분할의 핫스팟에 관한 통계에 액세스할 수 있습니다.
Spanner는 데이터를 테이블 및 색인의 기본 키 순으로 정렬된 연속 키 공간으로 저장합니다. 분할은 테이블 집합 또는 색인의 행 범위입니다. 분할의 시작을 분할 시작이라고 합니다. 분할 한도는 분할의 끝을 설정합니다. 분할에는 분할 시작이 포함되지만 분할 한도가 포함되지 않습니다.
Spanner에서 핫스팟은 동일한 서버로 전송되는 요청이 너무 많아서 서버의 리소스가 포화되고 지연 시간이 길어질 수 있는 상황을 말합니다. 핫스팟의 영향을 받는 분할을 핫 또는 웜 분할이라고 합니다.
분할의 핫스팟 통계(시스템에서 CPU_USAGE_SCORE
로 식별됨)는 서버에서 사용 가능한 리소스로 제약되는 분할의 부하를 측정한 값입니다. 이 측정값은 백분율로 표시됩니다. 분할의 부하 중 50% 이상이 사용 가능한 리소스로 제약되는 경우 분할은 웜으로 간주됩니다. 분할의 100% 부하가 제약된 경우 분할이 핫으로 간주됩니다.
Spanner는 부하 기반 분할을 사용하여 인스턴스의 서버에 데이터 부하를 균등하게 분산합니다. 웜 및 핫 분할은 부하 분산을 위해 서버 간에 이동하거나 더 작은 분할로 나눌 수 있습니다. 그러나 애플리케이션의 안티패턴으로 인해 Spanner가 여러 번 분할을 시도한 후에도 부하를 분산하지 못할 수 있습니다. 따라서 10분 이상 지속되는 지속적인 핫스팟의 경우 추가 문제 해결 및 잠재적인 애플리케이션 변경이 필요할 수 있습니다.
Spanner 핫 분할 통계를 사용하면 핫스팟이 발생하는 분할을 식별할 수 있습니다. 그런 다음 필요에 따라 애플리케이션 또는 스키마를 변경할 수 있습니다. SQL 문을 사용하여 SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
시스템 테이블에서 이러한 통계를 검색할 수 있습니다.
핫 분할 통계 가용성
Spanner는 SPANNER_SYS
스키마에서 핫 분할 통계를 제공합니다. SPANNER_SYS
데이터는 GoogleSQL 및 PostgreSQL 인터페이스를 통해서만 사용할 수 있습니다. 다음 방법을 사용하여 이 데이터에 액세스할 수 있습니다.
- Google Cloud 콘솔에 있는 데이터베이스의 Spanner 스튜디오 페이지
gcloud spanner databases execute-sql
명령어executeQuery
API
Spanner 단일 읽기 API는 SPANNER_SYS
를 지원하지 않습니다.
핫 분할 통계
다음 표를 사용하여 핫 분할을 추적합니다.
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
: 1분 간격 동안 핫 분할을 표시합니다.
이러한 테이블에는 다음과 같은 속성이 있습니다.
- 각 테이블에는 테이블 이름에 지정된 기간의 겹치지 않는 시간 간격에 대한 데이터가 포함되어 있습니다.
간격은 시계 시간을 기준으로 합니다.
- 1분 간격은 매분 정각에 끝납니다.
각 간격이 끝날 때마다 Spanner는 모든 서버에서 데이터를 수집한 다음 곧
SPANNER_SYS
테이블에 데이터를 제공합니다.예를 들어 오전 11:59:30에 SQL 쿼리에 사용할 수 있는 가장 최근 간격은 다음과 같습니다.
- 1분: 오전 11:58:00~11:58:59
Spanner는 분할별로 통계를 그룹화합니다.
각 행에는 Spanner가 지정된 간격 동안 통계를 캡처하는 각 분할에 대해 핫 또는 웜 상태인지를 나타내는 비율이 포함됩니다.
사용 가능한 리소스로 제약되는 분할의 부하가 50% 미만인 경우 Spanner는 통계를 캡처하지 않습니다. Spanner가 특정 간격 동안 모든 핫 분할을 저장할 수 없는 경우 시스템은 지정된 간격 동안
CPU_USAGE_SCORE
비율이 가장 높은 분할부터 우선순위를 지정합니다. 반환된 분할이 없으면 핫스팟이 없음을 나타냅니다.
테이블 스키마
다음 표에는 다음 통계의 테이블 스키마가 나와 있습니다.
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
열 이름 | 유형 | 설명 |
---|---|---|
INTERVAL_END |
TIMESTAMP |
분할이 가장 많이 사용되었던 시간 간격의 끝입니다. |
SPLIT_START |
STRING |
분할에서 행 범위의 시작 키입니다. 분할 시작은 키 공간의 시작을 나타내는 <begin> 일 수도 있습니다. |
SPLIT_LIMIT
|
STRING
|
분할에서 행 범위의 한도 키입니다. 한도 키는 키 공간의 끝을 나타내는 <end> 일 수도 있습니다. |
CPU_USAGE_SCORE
|
INT64
|
분할의 CPU_USAGE_SCORE 비율입니다. CPU_USAGE_SCORE 비율이 50%이면 웜 또는 핫 분할이 있음을 나타냅니다. |
AFFECTED_TABLES |
STRING ARRAY |
분할에 행이 있을 수 있는 테이블입니다. |
분할 시작 키 및 분할 한도 키
분할은 데이터베이스의 연속된 행 범위이며 시작 및 한도 키로 정의됩니다. 분할은 단일 행, 좁은 행 범위 또는 넓은 행 범위일 수 있으며 분할에는 여러 테이블 또는 색인이 포함될 수 있습니다.
SPLIT_START
및 SPLIT_LIMIT
열은 웜 또는 핫 분할의 기본 키를 식별합니다.
스키마 예시
다음 스키마는 이 페이지의 주제에 관한 예시 테이블입니다.
GoogleSQL
CREATE TABLE Users (
UserId INT64 NOT NULL,
FirstName STRING(MAX),
LastName STRING(MAX),
) PRIMARY KEY(UserId);
CREATE INDEX UsersByFirstName ON Users(FirstName DESC);
CREATE TABLE Threads (
UserId INT64 NOT NULL,
ThreadId INT64 NOT NULL,
Starred BOOL,
) PRIMARY KEY(UserId, ThreadId),
INTERLEAVE IN PARENT Users ON DELETE CASCADE;
CREATE TABLE Messages (
UserId INT64 NOT NULL,
ThreadId INT64 NOT NULL,
MessageId INT64 NOT NULL,
Subject STRING(MAX),
Body STRING(MAX),
) PRIMARY KEY(UserId, ThreadId, MessageId),
INTERLEAVE IN PARENT Threads ON DELETE CASCADE;
CREATE INDEX MessagesIdx ON Messages(UserId, ThreadId, Subject),
INTERLEAVE IN Threads;
PostgreSQL
CREATE TABLE users
(
userid BIGINT NOT NULL PRIMARY KEY,-- INT64 to BIGINT
firstname VARCHAR(max),-- STRING(MAX) to VARCHAR(MAX)
lastname VARCHAR(max)
);
CREATE INDEX usersbyfirstname
ON users(firstname DESC);
CREATE TABLE threads
(
userid BIGINT NOT NULL,
threadid BIGINT NOT NULL,
starred BOOLEAN, -- BOOL to BOOLEAN
PRIMARY KEY (userid, threadid),
CONSTRAINT fk_threads_user FOREIGN KEY (userid) REFERENCES users(userid) ON
DELETE CASCADE -- Interleave to Foreign Key constraint
);
CREATE TABLE messages
(
userid BIGINT NOT NULL,
threadid BIGINT NOT NULL,
messageid BIGINT NOT NULL PRIMARY KEY,
subject VARCHAR(max),
body VARCHAR(max),
CONSTRAINT fk_messages_thread FOREIGN KEY (userid, threadid) REFERENCES
threads(userid, threadid) ON DELETE CASCADE
-- Interleave to Foreign Key constraint
);
CREATE INDEX messagesidx ON messages(userid, threadid, subject), REFERENCES
threads(userid, threadid);
키 공간이 다음과 같다고 가정해 보겠습니다.
기본 키 |
---|
<begin> |
Users() |
Threads() |
Users(2) |
Users(3) |
Threads(3) |
Threads(3,"a") |
Messages(3,"a",1) |
Messages(3,"a",2) |
Threads(3, "aa") |
Users(9) |
Users(10) |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName("abcd") |
<end> |
분할 예시
다음은 분할의 모습을 이해하는 데 도움이 되는 몇 가지 분할 예시입니다.
SPLIT_START
및 SPLIT_LIMIT
는 테이블 또는 색인의 행을 나타낼 수도 있고, 데이터베이스의 키 공간 경계를 나타내는 <begin>
및 <end>
일 수도 있습니다. SPLIT_START
및 SPLIT_LIMIT
에는 테이블의 전체 키 앞에 오는 키인 잘린 키도 포함될 수 있습니다. 예를 들어 Threads(10)
는 Users(10)
에 인터리브 처리된 모든 Threads
행의 프리픽스입니다.
SPLIT_START | SPLIT_LIMIT | AFFECTED_TABLES | 설명 |
---|---|---|---|
Users(3) |
Users(10) |
UsersByFirstName , Users , Threads , Messages , MessagesIdx |
분할은 UserId=3 이 있는 행에서 시작하여 UserId = 10 이 있는 행 앞의 행에서 끝납니다. 분할에는 Users 테이블 행과 UserId=3 ~10의 모든 인터리브 처리된 테이블 행이 포함됩니다. |
Messages(3,"a",1) |
Threads(3,"aa") |
Threads , Messages , MessagesIdx |
분할은 UserId=3 , ThreadId="a" , MessageId=1 이 있는 행에서 시작하여 UserId=3 및 ThreadsId = "aa" 키가 있는 행 앞의 행에서 끝납니다. 분할에는 Messages(3,"a",1) 와 Threads(3,"aa") 사이의 모든 테이블이 포함됩니다. split_start 과 split_limit 는 동일한 최상위 테이블 행에 인터리브 처리되므로 분할에는 시작과 한도 사이의 인터리브 처리된 테이블 행이 포함됩니다. 인터리브 처리된 테이블이 어떻게 함께 배치되는지 알아보려면 schemas-overview를 참조하세요. |
Messages(3,"a",1) |
<end> |
UsersByFirstName , Users , Threads , Messages , MessagesIdx |
분할은 메시지 테이블에서 키가 UserId=3 , ThreadId="a" , MessageId=1 인 행에서 시작됩니다. 분할은 데이터베이스 키 공간의 끝인 split_start 에서 <end> 까지의 모든 행을 호스팅합니다. split_start 다음에 오는 테이블의 모든 행(예: Users(4) )이 분할에 포함됩니다. |
<begin> |
Users(9) |
UsersByFirstName , Users , Threads , Messages , MessagesIdx |
분할은 데이터베이스 키 공간의 시작인 <begin> 에서 시작하여 UserId=9 가 있는 Users 행 앞의 행에서 종료됩니다. 따라서 분할에는 Users 앞에 있는 모든 테이블 행과 UserId=9 앞에 있는 Users 테이블의 모든 행, 그리고 인터리브 처리된 테이블의 행이 포함됩니다. |
Messages(3,"a",1) |
Threads(10) |
UsersByFirstName , Users , Threads , Messages , MessagesIdx |
분할은 Users(3) 에 인터리브 처리된 Messages(3,"a", 1) 에서 시작하여 Threads(10) 앞의 행에서 끝납니다. Threads(10) 는 Users(10) 에 인터리브 처리된 Threads 테이블의 모든 키의 프리픽스인 잘린 분할 키입니다. |
Users() |
<end> |
UsersByFirstName , Users , Threads , Messages , MessagesIdx |
분할은 Users 테이블의 전체 키 앞에 오는 잘린 Users() 분할 키에서 시작됩니다. 분할은 데이터베이스의 가능한 키 공간 끝까지 확장됩니다. 따라서 affected_tables는 Users 테이블, 인터리브 처리된 테이블과 색인, 사용자 뒤에 표시될 수 있는 모든 테이블을 포함합니다. |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName , Users , Threads , Messages , MessagesIdx |
분할은 UserId = 10 이 있는 Threads 행에서 시작하여 "abc" 앞에 있는 키의 색인 UsersByFirstName 에서 끝납니다. |
핫 분할을 찾기 위한 쿼리 예시
다음 예시는 핫 분할 통계를 검색하는 데 사용할 수 있는 SQL 문을 보여줍니다. 이러한 SQL 문은 클라이언트 라이브러리, gcloud 또는 Google Cloud 콘솔을 사용하여 실행할 수 있습니다.
GoogleSQL
SELECT t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.interval_end =
(SELECT MAX(interval_end)
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE)
ORDER BY t.cpu_usage_score DESC;
PostgreSQL
SELECT t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.interval_end = (
SELECT MAX(interval_end)
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
)
ORDER BY t.cpu_usage_score DESC;
쿼리 출력은 다음과 같이 표시됩니다.
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
---|---|---|---|
Users(13) |
Users(76) |
82 |
Messages,Users,Threads |
Users(101) |
Users(102) |
90 |
Messages,Users,Threads |
Threads(10, "a") |
Threads(10, "aa") |
100 |
Messages,Threads |
Messages(631, "abc", 1) |
Messages(631, "abc", 3) |
100 |
Messages |
Threads(12, "zebra") |
Users(14) |
76 |
Messages,Users,Threads |
Users(620) |
<end> |
100 |
Messages,Users,Threads |
핫 분할 통계의 데이터 보관
Spanner는 각 테이블의 데이터를 최소한 다음 기간 동안 보관합니다.
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
: 이전 6시간을 포함하는 간격
핫 분할 통계를 사용하여 핫스팟 문제 해결
이 섹션에서는 핫스팟을 감지하고 문제를 해결하는 방법을 설명합니다.
조사 기간 선택
Spanner 데이터베이스의 지연 시간 측정항목을 확인하여 애플리케이션에서 지연 시간과 CPU 사용량이 높았던 기간을 찾습니다. 예를 들어 2024년 5월 18일 오후 10시 50분경에 문제가 발생했다고 표시될 수 있습니다.
지속적인 부하 집중 찾기
Spanner는 부하 기반 분할로 부하를 분산하므로 부하 집중이 10분 넘게 지속되었는지 조사하는 것이 좋습니다. 다음 예시와 같이 SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
테이블을 쿼리하면 됩니다.
GoogleSQL
SELECT Count(DISTINCT t.interval_end)
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.utilization >= 50
AND t.interval_end >= "interval_end_date_time"
AND t.interval_end <= "interval_end_date_time";
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
PostgreSQL
SELECT COUNT(DISTINCT t.interval_end)
FROM SPLIT_STATS_TOP_MINUTE t
WHERE t.utilization >= 50
AND t.interval_end >= 'interval_end_date_time'::timestamptz
AND t.interval_end <= 'interval_end_date_time'::timestamptz;
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
이전 쿼리 결과가 10과 같으면 데이터베이스에 추가 디버깅이 필요할 수 있는 부하 집중이 발생하고 있는 것입니다.
CPU_USAGE_SCORE
수준이 가장 높은 분할 찾기
이 예시에서는 다음 SQL을 실행하여 CPU_USAGE_SCORE
수준이 가장 높은 행 범위를 찾습니다.
GoogleSQL
SELECT t.split_start,
t.split_limit,
t.affected_tables,
t.cpu_usage_score
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.cpu_usage_score >= 50
AND t.interval_end = "interval_end_date_time";
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
PostgreSQL
SELECT t.split_start,
t.split_limit,
t.affected_tables,
t.cpu_usage_score
FROM SPLIT_STATS_TOP_MINUTE t
WHERE t.cpu_usage_score = 100
AND t.interval_end = 'interval_end_date_time'::timestamptz;
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
이전 SQL은 다음을 출력합니다.
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
---|---|---|---|
Users(180) |
<end> |
85 |
Messages,Users,Threads |
Users(24) |
Users(76) |
76 |
Messages,Users,Threads |
이 결과 테이블에서 두 분할에서 핫스팟이 발생한 것을 확인할 수 있습니다. Spanner 부하 기반 분할은 이러한 분할에서 핫스팟을 해결하려고 시도할 수 있습니다. 하지만 스키마나 워크로드에 문제가 있는 패턴이 있으면 불가능할 수 있습니다. 개입이 필요한 분할이 있는지 인식하려면 분할을 10분 이상 추적하는 것이 좋습니다. 예를 들어 다음 SQL은 지난 10분 동안의 첫 번째 분할을 추적합니다.
GoogleSQL
SELECT t.interval_end,
t.split_start,
t.split_limit,
t.cpu_usage_score
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.split_start = "users(180)"
AND t.split_limit = "<end>"
AND t.interval_end >= "interval_end_date_time"
AND t.interval_end <= "interval_end_date_time";
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
PostgreSQL
SELECT t.interval_end,
t.split_start,
t.split_limit,
t.cpu_usage_score
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.split_start = 'users(180)'
AND t.split_limit = ''
AND t.interval_end >= 'interval_end_date_time'::timestamptz
AND t.interval_end <= 'interval_end_date_time'::timestamptz;
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
이전 SQL은 다음을 출력합니다.
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
---|---|---|---|
2024-05-18T17:46:00Z |
Users(180) |
<end> |
85 |
2024-05-18T17:47:00Z |
Users(180) |
<end> |
85 |
2024-05-18T17:48:00Z |
Users(180) |
<end> |
85 |
2024-05-18T17:49:00Z |
Users(180) |
<end> |
85 |
2024-05-18T17:50:00Z |
Users(180) |
<end> |
85 |
지난 몇 분 동안 분할이 핫 상태였던 것으로 보입니다. Spanner 부하 기반 분할이 핫스팟을 완화하는지 확인하기 위해 분할을 더 오래 관찰할 수 있습니다. Spanner가 더 이상 부하를 분산할 수 없는 경우가 있을 수 있습니다.
예를 들어 SPANNER_SYS.SPLIT_STATS_TOP_MINUTE
테이블을 쿼리합니다. 다음 시나리오 예시를 참조하세요.
GoogleSQL
SELECT t.interval_end,
t.split_start,
t.split_limit,
t.cpu_usage_score
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.interval_end >= "interval_end_date_time"
AND t.interval_end <= "interval_end_date_time";
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
PostgreSQL
SELECT t.interval_end,
t.split_start,
t.split_limit,
t._cpu_usage
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.interval_end >= 'interval_end_date_time'::timestamptz
AND t.interval_end <= 'interval_end_date_time'::timestamptz;
interval_end_date_time을 2024-05-18T17:40:00Z
형식을 사용하여 간격의 날짜 및 시간으로 바꿉니다.
단일 핫 행
다음 예시에서 Threads(10,"spanner")
는 10분 넘게 핫 상태로 유지된 단일 행 분할에 있는 것 같습니다. 이는 인기 있는 행에 지속적인 부하가 있는 경우 발생할 수 있습니다.
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
---|---|---|---|
2024-05-16T20:40:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
62 |
2024-05-16T20:41:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
62 |
2024-05-16T20:42:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
62 |
2024-05-16T20:43:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
62 |
2024-05-16T20:44:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
62 |
2024-05-16T20:45:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
62 |
2024-05-16T20:46:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
80 |
2024-05-16T20:47:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
80 |
2024-05-16T20:48:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
80 |
2024-05-16T20:49:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
100 |
2024-05-16T20:50:00Z |
Threads(10,"spanner") |
Threads(10,"spanner1") |
100 |
Spanner는 이 단일 키를 더 이상 분할할 수 없으므로 이 키의 부하를 분산할 수 없습니다.
핫스팟 이동
다음 예시에서는 시간이 지남에 따라 부하가 연속된 분할을 통해 이동하여 시간 간격에 걸쳐 새 분할로 이동합니다.
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
---|---|---|---|
2024-05-16T20:40:00Z |
Threads(1,"a") |
Threads(1,"aa") |
100 |
2024-05-16T20:41:00Z |
Threads(1,"aa") |
Threads(1,"ab") |
100 |
2024-05-16T20:42:00Z |
Threads(1,"ab") |
Threads(1,"c") |
100 |
2024-05-16T20:43:00Z |
Threads(1,"c") |
Threads(1,"ca") |
100 |
예를 들어 키를 단조롭게 증가하는 순서대로 읽거나 쓰는 워크로드로 인해 이러한 문제가 발생할 수 있습니다. Spanner는 이러한 애플리케이션 동작의 영향을 완화하기 위해 부하를 분산할 수 없습니다.
일반 부하 분산
Spanner는 분할을 더 추가하거나 분할을 이동하여 부하를 분산하려고 시도합니다. 다음 예시는 이와 같은 모습을 보여줍니다.
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
---|---|---|---|
2024-05-16T20:40:00Z |
Threads(1000,"zebra") |
<end> |
82 |
2024-05-16T20:41:00Z |
Threads(1000,"zebra") |
<end> |
90 |
2024-05-16T20:42:00Z |
Threads(1000,"zebra") |
<end> |
100 |
2024-05-16T20:43:00Z |
Threads(1000,"zebra") |
Threads(2000,"spanner") |
100 |
2024-05-16T20:44:00Z |
Threads(1200,"c") |
Threads(2000) |
92 |
2024-05-16T20:45:00Z |
Threads(1500,"c") |
Threads(1700,"zach") |
76 |
2024-05-16T20:46:00Z |
Threads(1700) |
Threads(1700,"c") |
76 |
2024-05-16T20:47:00Z |
Threads(1700) |
Threads(1700,"c") |
50 |
2024-05-16T20:48:00Z |
Threads(1700) |
Threads(1700,"c") |
39 |
여기서 2024-05-16T17:40:00Z의 더 큰 분할이 더 작은 분할로 다시 분할되었고 그 결과 CPU_USAGE_SCORE
통계가 감소했습니다.
Spanner는 개별 행으로 분할을 만들지 않을 수도 있습니다. 분할은 CPU_USAGE_SCORE
통계가 높아지는 원인이 되는 워크로드를 반영합니다.
10분 넘게 핫 분할이 지속되는 경우 핫스팟 완화를 위한 권장사항을 참조하세요.
핫스팟 완화를 위한 권장사항
부하 분산으로 지연 시간이 줄어들지 않으면 다음 단계는 핫스팟의 원인을 파악하는 것입니다. 그런 다음 부하 집중 워크로드를 줄이거나 핫스팟을 방지하도록 애플리케이션 스키마와 로직을 최적화할 수 있습니다.
원인 파악
잠금 및 트랜잭션 통계를 사용하여 행 범위 시작 키가 핫 분할 내에 있는 잠금 대기 시간이 긴 트랜잭션을 찾습니다.
쿼리 통계를 사용하여 핫 분할이 포함된 테이블에서 읽고 최근에 지연 시간이 증가했거나 CPU에 대한 지연 시간 비율이 더 높은 쿼리를 찾습니다.
가장 오래된 활성 쿼리를 사용하여 핫 분할이 포함된 테이블에서 읽고 예상보다 지연 시간이 긴 쿼리를 찾습니다.
주의해야 할 몇 가지 특수한 경우는 다음과 같습니다.
- 최근에 TTL(수명)이 사용 설정되었는지 확인합니다. 이전 데이터의 분할이 많은 경우 TTL은 일괄 삭제 중에
CPU_USAGE_SCORE
수준을 높일 수 있습니다. 이 경우 초기 삭제가 완료되면 문제가 자동으로 해결됩니다.
워크로드 최적화
- SQL 권장사항을 따릅니다. 비활성 읽기, 먼저 읽기를 수행하지 않는 쓰기 또는 색인 추가를 고려하세요.
- 스키마 권장사항을 따릅니다. 스키마가 부하 분산을 처리하고 핫스팟을 방지하도록 설계되었는지 확인합니다.
다음 단계
- 스키마 설계 권장사항 알아보기
- Key Visualizer 알아보기
- 스키마 설계 예시 살펴보기
- 분할 통계 대시보드를 사용하여 핫스팟을 감지하는 방법 알아보기14