Spanner는 테이블(변경 내역 테이블 포함) 및 색인에 대한 읽기(또는 쿼리), 쓰기, 삭제 작업 통계를 기록하는 기본 제공 테이블을 제공합니다. 테이블 작업 통계로 다음을 수행할 수 있습니다.
스토리지 증가에 따라 쓰기 트래픽이 증가한 테이블을 식별합니다.
예기치 않은 읽기, 쓰기, 삭제 트래픽이 있는 테이블을 식별합니다.
많이 사용되는 테이블을 식별합니다.
테이블에 쿼리하거나 쓰는 경우 액세스된 행 수에 관계없이 테이블의 해당 작업 수는 1씩 증가합니다.
시스템 통계 차트의 Operations per second, Operations per second by API method, 기타 관련 측정항목을 사용하여 데이터베이스의 전체 초당 작업 측정항목을 모니터링할 수 있습니다.
가용성
Spanner는 SPANNER_SYS 스키마에서 테이블 작업 통계를 제공합니다. SPANNER_SYS 데이터는 SQL 인터페이스를 통해서만 사용할 수 있습니다. 예를 들면 다음과 같습니다.
Google Cloud 콘솔에 있는 데이터베이스의 Spanner Studio 페이지
gcloud spanner databases execute-sql 명령어
executeQuery API
Spanner가 제공하는 다른 단일 읽기 메서드는 SPANNER_SYS를 지원하지 않습니다.
테이블 작업 통계
다음 테이블은 특정 기간 동안 테이블과 색인의 읽기(또는 쿼리), 쓰기, 삭제 통계를 추적합니다.
SPANNER_SYS.TABLE_OPERATIONS_STATS_MINUTE: 1분 간격 동안의 작업
SPANNER_SYS.TABLE_OPERATIONS_STATS_10MINUTE: 10분 간격 동안의 작업
SPANNER_SYS.TABLE_OPERATIONS_STATS_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
모든 테이블 작업 통계 테이블의 스키마
열 이름
유형
설명
INTERVAL_END
TIMESTAMP
테이블 크기가 수집된 종료 시간 간격입니다.
TABLE_NAME
STRING
테이블 또는 색인의 이름입니다.
READ_QUERY_COUNT
INT64
테이블에서 읽는 쿼리 또는 읽기 수입니다.
WRITE_COUNT
INT64
테이블에 쓰는 쿼리 수입니다.
DELETE_COUNT
INT64
테이블에서 삭제를 수행하는 쿼리 수입니다.
변형을 사용하여 데이터베이스에 데이터를 삽입하면 write_count에서 삽입 문으로 액세스되는 테이블마다 1씩 증가합니다. 또한 기본 테이블을 스캔하지 않고 색인에 액세스하는 쿼리는 색인에서 read_query_count만 증가합니다.
데이터 보관
Spanner는 각 테이블의 데이터를 최소한 다음 기간 동안 보관합니다.
SPANNER_SYS.TABLE_OPERATIONS_STATS_MINUTE: 지난 6시간을 포함하는 간격
SPANNER_SYS.TABLE_OPERATIONS_STATS_10MINUTE:지난 4일을 포함하는 간격
SPANNER_SYS.TABLE_OPERATIONS_STATS_HOUR: 지난 30일을 포함하는 간격
쿼리 예시
이 섹션에는 집계 테이블 작업 통계를 검색하는 SQL 문의 몇 가지 예시가 포함되어 있습니다. 클라이언트 라이브러리 또는 gcloud spanner를 사용하여 이러한 SQL 문을 실행할 수 있습니다.
가장 최근 간격 동안 쓰기 작업이 가장 많은 테이블 및 색인 쿼리
SELECT interval_end,
table_name,
write_count
FROM spanner_sys.table_operations_stats_minute
WHERE interval_end = (
SELECT MAX(interval_end)
FROM spanner_sys.table_operations_stats_minute)
ORDER BY write_count DESC;
가장 최근 간격 동안 삭제 작업이 가장 많은 테이블 및 색인 쿼리
SELECT interval_end,
table_name,
delete_count
FROM spanner_sys.table_operations_stats_minute
WHERE interval_end = (
SELECT MAX(interval_end)
FROM spanner_sys.table_operations_stats_minute)
ORDER BY delete_count DESC;
가장 최근 간격 동안 읽기 및 쿼리 작업이 가장 많은 테이블 및 색인 쿼리
SELECT interval_end,
table_name,
read_query_count
FROM spanner_sys.table_operations_stats_minute
WHERE interval_end = (
SELECT MAX(interval_end)
FROM spanner_sys.table_operations_stats_minute)
ORDER BY read_query_count DESC;
지난 6시간 동안의 테이블 사용량 쿼리
GoogleSQL
SELECT interval_end,
read_query_count,
write_count,
delete_count
FROM spanner_sys.table_operations_stats_minute
WHERE table_name = "table_name"
ORDER BY interval_end DESC;
각 항목의 의미는 다음과 같습니다.
table_name은 데이터베이스의 기존 테이블 또는 색인이어야 합니다.
PostgreSQL
SELECT interval_end,
read_query_count,
write_count,
delete_count
FROM spanner_sys.table_operations_stats_minute
WHERE table_name = 'table_name'
ORDER BY interval_end DESC;
각 항목의 의미는 다음과 같습니다.
table_name은 데이터베이스의 기존 테이블 또는 색인이어야 합니다.
지난 14일 동안의 테이블 사용량 쿼리
GoogleSQL
SELECT interval_end,
read_query_count,
write_count,
delete_count
FROM spanner_sys.table_operations_stats_hour
WHERE interval_end > TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -14 DAY)
AND table_name = "table_name"
ORDER BY interval_end DESC;
각 항목의 의미는 다음과 같습니다.
table_name은 데이터베이스의 기존 테이블 또는 색인이어야 합니다.
PostgreSQL
SELECT interval_end,
read_query_count,
write_count,
delete_count
FROM spanner_sys.table_operations_stats_hour
WHERE interval_end > spanner.timestamptz_subtract(now(), '14 DAY')
AND table_name = 'table_name'
ORDER BY interval_end DESC;
각 항목의 의미는 다음과 같습니다.
table_name은 데이터베이스의 기존 테이블 또는 색인이어야 합니다.
지난 24시간 동안 사용량이 없는 테이블 및 색인 쿼리
GoogleSQL
(SELECT t.table_name
FROM information_schema.tables AS t
WHERE t.table_catalog = ""
AND t.table_schema = ""
AND t.table_type = "BASE TABLE"
UNION ALL
SELECT cs.change_stream_name
FROM information_schema.change_streams cs
WHERE cs.change_stream_catalog = ""
AND cs.change_stream_schema = ""
UNION ALL
SELECT idx.index_name
FROM information_schema.indexes idx
WHERE idx.index_type = "INDEX"
AND idx.table_catalog = ""
AND idx.table_schema = "")
EXCEPT ALL
(SELECT DISTINCT(table_name)
FROM spanner_sys.table_operations_stats_hour
WHERE interval_end > TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -24 HOUR));
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-05-22(UTC)"],[],[],null,["# Table operations statistics\n\nSpanner provides built-in tables that records the read (or query),\nwrite, and delete operations statistics for your tables (including change\nstreams tables) and indexes. With table operations statistics you can do the\nfollowing:\n\n- Identify tables with increased write traffic corresponding\n to storage increase.\n\n- Identify tables with unexpected read, write, and delete traffic.\n\n- Identify heavily-used tables.\n\nWhen you query or write to a table, the corresponding operation count for the\ntable increments by 1, regardless of the number of rows accessed.\n\nOverall operations-per-second metrics of a database can be monitored with\n`Operations per second`, `Operations per second by API method`, and other\nrelated metrics in your [System Insights](/spanner/docs/monitoring-console)\ncharts.\n| **Note:** The sum of the operation counts on all tables and indexes might not be equal to the total operations on a database. For example, one write to a table increments the `write_count` on the table and on all indexes on the table. However, the write only counts as one operation on the database. The operation counts don't depend on the number of rows read or written to. They track the number of operations only. When the PartitionRead or PartitionQuery API returns multiple partition tokens, each Read or ExecuteSql call with a different token counts as a separate table operation.\n\nAccess table operations statistics\n----------------------------------\n\nSpanner provides the table operations statistics in the\n`SPANNER_SYS` schema.You can use the following ways to access `SPANNER_SYS` data:\n\n- A database's Spanner Studio page in the Google Cloud console.\n\n- The `gcloud spanner databases execute-sql` command.\n\n- The [`executeSql`](/spanner/docs/reference/rest/v1/projects.instances.databases.sessions/executeSql)\n or the [`executeStreamingSql`](/spanner/docs/reference/rest/v1/projects.instances.databases.sessions/executeStreamingSql)\n method.\n\nThe following single read methods that Spanner provides\ndon't support `SPANNER_SYS`:\n\n- Performing a strong read from a single row or multiple rows in a table.\n- Performing a stale read from a single row or multiple rows in a table.\n- Reading from a single row or multiple rows in a secondary index.\n\nTable operations statistics\n---------------------------\n\nThe following tables track the read (or query), write, and delete statistics on your\ntables and indexes during a specific time period:\n\n- `SPANNER_SYS.TABLE_OPERATIONS_STATS_MINUTE`: Operations during 1 minute intervals\n- `SPANNER_SYS.TABLE_OPERATIONS_STATS_10MINUTE`: Operations during 10 minute intervals\n- `SPANNER_SYS.TABLE_OPERATIONS_STATS_HOUR`: Operations during 1 hour intervals\n\nThese tables have the following properties:\n\n- Each table contains data for non-overlapping time intervals of the length that\n the table name specifies.\n\n- Intervals are based on clock times. 1 minute intervals start on the minute, 10\n minute intervals start every 10 minutes starting on the hour, and 1 hour\n intervals start on the hour.\n\n For example, at 11:59:30 AM, the most recent intervals available to SQL\n queries are:\n - **1 minute**: 11:58:00--11:58:59 AM\n - **10 minute**: 11:40:00--11:49:59 AM\n - **1 hour**: 10:00:00--10:59:59 AM\n\n### Schema for all table operations statistics tables\n\nIf you insert data into your database using mutations, the `write_count`\nincrements by 1 for each table accessed by the insert statement. In addition,\na query that accesses an index, without scanning the underlying table, only\nincrements the `read_query_count` on the index.\n\nData retention\n--------------\n\nAt a minimum, Spanner keeps data for each table for the following\ntime periods:\n\n- `SPANNER_SYS.TABLE_OPERATIONS_STATS_MINUTE`: Intervals covering the previous 6\n hours.\n\n- `SPANNER_SYS.TABLE_OPERATIONS_STATS_10MINUTE`: Intervals covering the previous\n 4 days.\n\n- `SPANNER_SYS.TABLE_OPERATIONS_STATS_HOUR`: Intervals covering the previous 30\n days.\n\n| **Note:** You cannot prevent Spanner from collecting table operations statistics. To delete the data in these tables, you must delete the database associated with the tables or wait until Spanner removes the data automatically.\n\n### Example queries\n\nThis section includes several example SQL statements that retrieve aggregate\ntable operations statistics. You can run these SQL statements using the\n[client libraries](/spanner/docs/reference/libraries), or the\n[gcloud spanner](/spanner/docs/gcloud-spanner#execute_sql_statements).\n\n#### Query the tables and indexes with the most write operations for the most recent interval\n\n```\n SELECT interval_end,\n table_name,\n write_count\n FROM spanner_sys.table_operations_stats_minute\n WHERE interval_end = (\n SELECT MAX(interval_end)\n FROM spanner_sys.table_operations_stats_minute)\n ORDER BY write_count DESC;\n \n```\n\n#### Query the tables and indexes with the most delete operations for the most recent interval\n\n```\n SELECT interval_end,\n table_name,\n delete_count\n FROM spanner_sys.table_operations_stats_minute\n WHERE interval_end = (\n SELECT MAX(interval_end)\n FROM spanner_sys.table_operations_stats_minute)\n ORDER BY delete_count DESC;\n \n```\n\n#### Query the tables and indexes with the most read and query operations for the most recent interval\n\n```\n SELECT interval_end,\n table_name,\n read_query_count\n FROM spanner_sys.table_operations_stats_minute\n WHERE interval_end = (\n SELECT MAX(interval_end)\n FROM spanner_sys.table_operations_stats_minute)\n ORDER BY read_query_count DESC;\n \n```\n\n#### Query the usage of a table over the last 6 hours\n\n### GoogleSQL\n\n```\n SELECT interval_end,\n read_query_count,\n write_count,\n delete_count\n FROM spanner_sys.table_operations_stats_minute\n WHERE table_name = \"table_name\"\n ORDER BY interval_end DESC;\n \n```\n\nWhere:\n\n- \u003cvar translate=\"no\"\u003e\u003ccode translate=\"no\" dir=\"ltr\"\u003etable_name\u003c/code\u003e\u003c/var\u003e must be an existing table or index in the database.\n\n### PostgreSQL\n\n```\n SELECT interval_end,\n read_query_count,\n write_count,\n delete_count\n FROM spanner_sys.table_operations_stats_minute\n WHERE table_name = 'table_name'\n ORDER BY interval_end DESC;\n \n```\n\nWhere:\n\n- \u003cvar translate=\"no\"\u003e\u003ccode translate=\"no\" dir=\"ltr\"\u003etable_name\u003c/code\u003e\u003c/var\u003e must be an existing table or index in the database.\n\n#### Query the usage of a table over the last 14 days\n\n### GoogleSQL\n\n```\nSELECT interval_end,\n read_query_count,\n write_count,\n delete_count\nFROM spanner_sys.table_operations_stats_hour\nWHERE interval_end \u003e TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -14 DAY)\n AND table_name = \"table_name\"\nORDER BY interval_end DESC;\n```\n\nWhere:\n\n- \u003cvar translate=\"no\"\u003e\u003ccode translate=\"no\" dir=\"ltr\"\u003etable_name\u003c/code\u003e\u003c/var\u003e must be an existing table or index in the database.\n\n### PostgreSQL\n\n```\nSELECT interval_end,\n read_query_count,\n write_count,\n delete_count\nFROM spanner_sys.table_operations_stats_hour\nWHERE interval_end \u003e spanner.timestamptz_subtract(now(), '14 DAY')\n AND table_name = 'table_name'\nORDER BY interval_end DESC;\n```\n\nWhere:\n\n- \u003cvar translate=\"no\"\u003e\u003ccode translate=\"no\" dir=\"ltr\"\u003etable_name\u003c/code\u003e\u003c/var\u003e must be an existing table or index in the database.\n\n#### Query the tables and indexes with no usage in the last 24 hours\n\n### GoogleSQL\n\n```\n(SELECT t.table_name\n FROM information_schema.tables AS t\n WHERE t.table_catalog = \"\"\n AND t.table_schema = \"\"\n AND t.table_type = \"BASE TABLE\"\n UNION ALL\n SELECT cs.change_stream_name\n FROM information_schema.change_streams cs\n WHERE cs.change_stream_catalog = \"\"\n AND cs.change_stream_schema = \"\"\n UNION ALL\n SELECT idx.index_name\n FROM information_schema.indexes idx\n WHERE idx.index_type = \"INDEX\"\n AND idx.table_catalog = \"\"\n AND idx.table_schema = \"\")\n EXCEPT ALL\n(SELECT DISTINCT(table_name)\n FROM spanner_sys.table_operations_stats_hour\n WHERE interval_end \u003e TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -24 HOUR));\n```\n\nWhat's next\n-----------\n\n- Use [Table sizes statistics](/spanner/docs/introspection/table-sizes-statistics)\n to determine the sizes of your tables and indexes.\n\n- Learn about other [Introspection tools](/spanner/docs/introspection).\n\n- Learn more about [SQL best practices](/spanner/docs/sql-best-practices) for\n Spanner."]]