쿼리 통계는 Cloud SQL 데이터베이스의 쿼리 성능 문제를 감지하고 진단하고 방지하는 데 도움이 됩니다.
쿼리 통계에서는 장기 실행 쿼리 목록과 함께 설명 계획(PostgreSQL 문서)을 제공합니다.
설명 계획을 검토하고 높은 메모리 사용량 스캔 메서드가 있는 쿼리 부분을 식별합니다.
쿼리 실행 시간에 관계없이 쿼리 통계는 모든 쿼리의 실행 계획을 제공합니다. 더 많은 시간이 소요되는 복잡한 쿼리를 식별하여 어떤 쿼리가 메모리를 오랫동안 차단하는지 파악합니다.
많은 메모리를 사용하는 일반적인 PostgreSQL 스캔 메서드는 다음과 같습니다.
비트맵 힙 스캔
빠른 정렬
해시 조인 또는 해시
Gemini 지원 인스턴스의 높은 메모리 사용량 및 관련 로그
데이터베이스 다운타임으로 이어지는 메모리 부족(OOM) 대신 Gemini가 사용 설정된 경우 메모리 사용량이 높은 쿼리 실행 연결을 종료하여 데이터베이스 다운타임을 방지합니다. 문제 원인이 되는 쿼리를 찾으려면 데이터베이스 로그에서 다음 항목을 확인할 수 있습니다.
(...timestamp….) db=postgres, user=customer FATAL: terminating connection due to administrator command
OOM 방지를 위해 종료된 높은 메모리 사용 쿼리를 캡처하는 다음 PostgreSQL용 Cloud SQL 데이터베이스 로그가 표시됩니다. 쿼리는 원래 쿼리가 정규화된 버전입니다.
db=postgres,user=customer LOG: postgres process with PID 1734 for the query "SELECT COUNT(product) AS item_count FROM test_table WHERE product_type = $1 AND product LIKE $2 AND c6_2 IN ($3,$4,$5,$6,$7)" has been cancelled.
다음 이벤트의 경우 Cloud SQL 인스턴스 페이지에도 알림이 표시됩니다.
지난 24시간 동안 인스턴스의 메모리 사용량
지난 24시간 내에 취소된 정규화된 쿼리 목록
메모리 사용량 최적화에 대한 Google 문서 링크
높은 메모리 사용량 - 권장사항
다음 권장사항은 일반적인 메모리 관련 문제를 해결합니다.
인스턴스에서 계속 높은 메모리 용량을 사용하면 결국 out of memory 문제가 발생했을 확률이 높습니다.
PostgreSQL 또는 다른 프로세스의 메모리 수요로 인해 시스템 메모리가 부족해지면 PostgreSQL 로그에 Out of Memory 커널 메시지가 표시되고 PostgreSQL 인스턴스가 결국 중지됩니다.
예를 들면 다음과 같습니다.
Out of Memory: Killed process 12345 (postgres)
OOM 문제가 발생하는 가장 일반적인 경우는 활성 연결 수가 많은 work_mem 값이 높을 때입니다.
따라서 OOM이 자주 발생하는 경우 또는 PostgreSQL용 Cloud SQL 인스턴스에서 OOM을 방지하기 위해서는 다음 권장사항을 따르는 것이 좋습니다.
work_mem 설정
빠른 정렬을 사용하는 쿼리가 외부 병합 정렬을 사용하는 쿼리보다 빠릅니다. 하지만 전자는 메모리 소진을 일으킬 수 있습니다.
이 문제를 해결하려면 메모리와 디스크에서 이루어지는 정렬 작업이 모두 균형을 이룰 정도로 work_mem 값을 충분히 설정합니다.
또한 전체 인스턴스에 대해 설정하지 않고 세션 수준에서 work_mem을 설정할 수 있습니다.
활성 세션 모니터링
각 연결은 특정 메모리 용량을 사용합니다. 다음 쿼리를 사용해서 활성 연결 수를 확인합니다.
SELECT
state,
usename,
count(1)
FROM
pg_stat_activity
WHERE
pid <> pg_backend_pid()
GROUP BY
state,
usename
ORDER BY
1;
활성 세션이 많은 경우 활성 세션 수가 많은 근본 원인(예: 트랜잭션 잠금)을 분석합니다.
shared_buffers 설정
shared_buffers가 높은 값으로 설정된 경우 work_mem과 같은 다른 작업이나 새 연결 설정에 메모리를 사용할 수 있도록 shared_buffers 값을 줄이는 것이 좋습니다.
캐시 적중률
PostgreSQL은 일반적으로 가장 자주 액세스하는 데이터를 캐시에 보관하려고 합니다. 클라이언트에서 데이터를 요청할 때 데이터가 이미 공유 버퍼에 캐시된 경우 해당 클라이언트에 직접 제공됩니다. 이것을 캐시 적중이라고 합니다.
공유 버퍼에 데이터가 없는 경우에는 먼저 데이터를 디스크의 공유 버퍼로 가져온 다음 클라이언트에 제공합니다.
이를 캐시 부적중이라고 부릅니다. 캐시 적중률은 캐시가 처리한 콘텐츠 요청을 수신된 요청과 비교해서 측정합니다.
PostgreSQL 인스턴스의 테이블 요청에 대한 캐시 적중률을 확인하려면 다음 쿼리를 실행합니다.
SELECT
sum(heap_blks_read) as heap_read,
sum(heap_blks_hit) as heap_hit,
sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio
FROM
pg_statio_user_tables;
PostgreSQL 인스턴스의 색인 요청에 대한 캐시 적중률을 확인하려면 다음 쿼리를 실행합니다.
SELECT
sum(idx_blks_read) as idx_read,
sum(idx_blks_hit) as idx_hit,
(sum(idx_blks_hit) - sum(idx_blks_read)) / sum(idx_blks_hit) as ratio
FROM
pg_statio_user_indexes;
일반적으로 95~99%의 캐시 적중률이 적절한 값으로 간주됩니다.
PostgreSQL용 Cloud SQL에서는 메모리 관리를 개선하기 위해 huge_pages 플래그가 기본적으로 사용 설정되어 있습니다. huge_pages에 대한 자세한 내용은 PostreSQL 문서를 참조하세요.
max_locks_per_transaction 설정
max_locks_per_transaction 값은 동시에 잠글 수 있는 데이터베이스 객체 수를 나타냅니다.
대부분의 경우 기본값인 64개면 충분합니다. 하지만 작업 중인 데이터 세트 규모가 크면 OOM이 발생할 수 있습니다. OOM을 방지할 수 있도록 max_locks_per_transaction 값을 충분히 높이는 것이 좋습니다.
max_locks_per_transaction 값은 max_locks_per_transaction * (max_connections + max_prepared_transactions)개의 객체여야 합니다.
즉, 객체가 300,000개이고 max_connections 값이 200이면 max_locks_per_transaction은 1,500이어야 합니다.
max_pred_locks_per_transaction 설정
직렬화 가능한 단일 트랜잭션에서 여러 테이블을 다루는 클라이언트가 있는 경우 트랜잭션이 실패할 수 있습니다.
이 시나리오에서는 max_pred_locks_per_transaction을 상당히 높은 값으로 늘리는 것이 좋습니다.
max_locks_per_transaction과 마찬가지로 max_pred_locks_per_transaction도 공유 메모리를 사용하므로 지나치게 높은 값을 설정하지는 마세요.
메모리 사용량이 여전히 높고 쿼리가 타당한 트래픽이라고 생각되면 인스턴스의 메모리 리소스 수를 늘려 데이터베이스 비정상 종료나 다운타임을 방지하세요.
[[["이해하기 쉬움","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-08-19(UTC)"],[],[],null,["# Optimize high memory usage in instances\n\n\u003cbr /\u003e\n\n[MySQL](/sql/docs/mysql/optimize-high-memory-usage \"View this page for the MySQL database engine\") \\| PostgreSQL \\| [SQL Server](/sql/docs/sqlserver/optimize-high-memory-usage \"View this page for the SQL Server database engine\")\n\n\u003cbr /\u003e\n\nThis document covers how to identify high memory usage for Cloud SQL instances and provides recommendations on how to solve memory-related issues.\n\nTo learn how to configure memory usage for a Cloud SQL instance, see [Best practices for managing memory usage](/sql/docs/postgres/manage-memory-usage-best-practices).\n\nIdentify high memory usage\n--------------------------\n\nThe following sections discuss high memory usage scenarios.\n\n### Use Metrics Explorer to identify the memory usage\n\nYou can review memory usage of the instance with the\n[`database/memory/components.usage`](/sql/docs/postgres/admin-api/metrics) metric in\n[Metrics Explorer](/monitoring/charts/metrics-explorer).\n| **Note:** If you have less than 10% memory in `database/memory/components.cache` and `database/memory/components.free` combined, the risk of an OOM event is high. To monitor the memory usage and to prevent OOM events, we recommend that you set up an [alerting policy](/monitoring/alerts) with a metric threshold condition of 90% in `database/memory/components.usage`.\n\n### Use Query insights to analyse explain plan for queries that are consuming high resources\n\n[Query insights](/sql/docs/postgres/using-query-insights) helps you detect, diagnose, and prevent query performance problems for Cloud SQL databases.\nQuery insights gives you a list of long running queries along with their [explain plan (PostgreSQL documentation)](https://www.postgresql.org/docs/current/sql-explain.html).\nReview the explain plan and identify the part of the query that has a high memory usage scan method.\nRegardless of the query run time, query insights gives you the explain plan for all queries. Identify the complex queries that are taking more time so that you know which queries are blocking the memory for longer durations.\n\nCommon PostgreSQL scan methods that use high memory include the following:\n\n- Bitmap heap scan\n- Quick sort\n- Hash join or Hash\n\nHigh memory usage and relevant logs for Gemini-enabled instances\n----------------------------------------------------------------\n\n|\n| **Preview\n| --- [Gemini in Databases](/gemini/docs/overview)**\n|\n|\n| This feature is subject to the \"Pre-GA Offerings Terms\" in the General Service Terms section\n| of the [Service Specific Terms](/terms/service-terms#1).\n|\n| You can process personal data for this feature as outlined in the\n| [Cloud Data Processing\n| Addendum](/terms/data-processing-addendum), subject to the obligations and restrictions described in the agreement under\n| which you access Google Cloud.\n|\n| Pre-GA features are available \"as is\" and might have limited support.\n|\n| For more information, see the\n| [launch stage descriptions](/products#product-launch-stages).\n\nIf you have [Gemini](/gemini/docs/overview) enabled, instead of an out-of-memory (OOM) failure which leads to database downtime, a connection executing a query with high memory usage is terminated thereby preventing database downtime. To identify the defaulting query, you can check the database logs for the following entries: \n\n (...timestamp....) db=postgres, user=customer FATAL: terminating connection due to administrator command\n\nThe following Cloud SQL for PostgreSQL database log is displayed which captures the high memory usage query that was terminated to prevent OOM. The query is a normalized version of the original query: \n\n db=postgres,user=customer LOG: postgres process with PID 1734 for the query \"SELECT COUNT(product) AS item_count FROM test_table WHERE product_type = $1 AND product LIKE $2 AND c6_2 IN ($3,$4,$5,$6,$7)\" has been cancelled.\n\nNotifications are also displayed on the **Cloud SQL Instances** page for the following events:\n\n- Memory utilization of the instance over the last 24 hours.\n- List of normalized queries that have been canceled within the past 24 hours.\n- A link to Google documentation about optimizing memory usage.\n\nHigh Memory Usage - Recommendations\n-----------------------------------\n\nThe following recommendations address the common memory-related problems.\nIf the instance continues to use a high amount of memory, chances are high that it eventually gets an `out of memory` issue.\nIf the memory demands of either PostgreSQL or another process cause the system to run out of memory, you see an `Out of Memory` kernel message in PostgreSQL logs and the PostgreSQL instance is eventually stopped.\nFor example: \n\n Out of Memory: Killed process 12345 (postgres)\n\nThe most common instance where you see an OOM issue is with a higher value of `work_mem` with a high number of active connections.\nTherefore, if you are getting frequent OOMs or to avoid OOMs in your Cloud SQL for PostgreSQL instance, you should consider following these recommendations:\n\n- Set `work_mem`\n\n Queries that use quick sort are faster than the ones using external merge sort. However, the former may lead to memory exhaustion.\n To resolve this issue, set the `work_mem` value reasonable enough such that it balances both, the sort operations happening in the memory and disk.\n You can also consider setting `work_mem` on a session level rather than setting it for an entire instance.\n- Monitor the active sessions\n\n Each connection uses a certain amount of memory. Use the following query to check the active connections count: \n\n SELECT\n state,\n usename,\n count(1)\n FROM\n pg_stat_activity\n WHERE\n pid \u003c\u003e pg_backend_pid()\n GROUP BY\n state,\n usename\n ORDER BY\n 1;\n\n If you have a large number of active sessions, analyze the root cause for a high number of active sessions; for example, transaction locks.\n- Set `shared_buffers`\n\n If `shared_buffers` is set to a higher value, consider decreasing the `shared_buffers` value so that the memory can be used for other operations, such as `work_mem`, or for establishing new connections.\n\n **Cache hit ratio**\n\n PostgreSQL generally tries to keep the data you access most often in the cache. When the data is requested by a client,\n if it's already cached in shared buffers, it's directly given to the client. This is called a *cache hit* .\n If the data is not present in shared buffers, the data is first fetched to shared buffers from a disk and then given to the client.\n This is called a *cache miss*.\n Cache hit ratio measures how many content requests the cache has handled compared to the requests received.\n Run the following query to check the cache hit ratio for the table requests in the PostgreSQL instance: \n\n SELECT\n sum(heap_blks_read) as heap_read,\n sum(heap_blks_hit) as heap_hit,\n sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio\n FROM\n pg_statio_user_tables;\n\n Run the following query to check the cache hit ratio for the index requests in the PostgreSQL instance: \n\n SELECT\n sum(idx_blks_read) as idx_read,\n sum(idx_blks_hit) as idx_hit,\n (sum(idx_blks_hit) - sum(idx_blks_read)) / sum(idx_blks_hit) as ratio\n FROM\n pg_statio_user_indexes;\n\n Generally, 95 to 99% of cache hit ratio is considered to be a good value.\n- In Cloud SQL for PostgreSQL, the `huge_pages` flag is enabled by default for better\n memory management. To learn more about `huge_pages`, see\n [PostreSQL documentation](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-HUGE-PAGES).\n\n- Set `max_locks_per_transaction`\n\n The `max_locks_per_transaction` value indicates the number of database objects that can be locked simultaneously.\n In most cases, the default value of 64 is sufficient. However, if you are dealing with a large dataset, you may end up with OOMs. Consider increasing the value\n of `max_locks_per_transaction` high enough to avoid OOMs.\n | **Note:** The object-level locking happens in memory on an ongoing transaction, Increasing the `max_prepared_transactions` value unreasonably high can cause the database instance to request more shared memory.\n\n The `max_locks_per_transaction` value should be `max_locks_per_transaction` \\* (`max_connections` + `max_prepared_transactions`) objects.\n This means that if you have 300 thousand objects, and if the value of `max_connections` is 200, then `max_locks_per_transaction` should be 1500.\n- Set `max_pred_locks_per_transaction`\n\n The transaction might fail if you have clients that touch many different tables in a single serializable transaction.\n In that scenario, consider increasing `max_pred_locks_per_transaction` to a reasonably high value.\n Like `max_locks_per_transaction`, `max_pred_locks_per_transaction` also uses shared memory so don't set an unreasonable high value.\n- If the memory usage is still high and you feel those queries are legitimate traffic, then consider increasing the number of memory resources in your instance to avoid database crash or downtime.\n\nWhat's next\n-----------\n\n- [Google Cloud recommenders](/recommender/docs/recommenders)"]]