DBAtlas · 데이터베이스 운영 아틀라스

바인드 변수 / 파라미터 스니핑 관리

Oracle

-- Use binds instead of literals (for plan sharing):
SELECT * FROM customer WHERE city = :city;
-- Share legacy code that uses literals:
ALTER SESSION SET cursor_sharing = FORCE;

바인드 변수는 hard parse를 줄인다. Adaptive Cursor Sharing은 분포가 치우친 바인드 값에 대해 여러 실행 계획을 유지해 스니핑 문제를 완화한다. cursor_sharing=FORCE는 신중하게 사용한다.

PostgreSQL

-- Parameterize with a prepared statement:
PREPARE q (text) AS SELECT * FROM customer WHERE city = $1;
EXECUTE q('Ankara');
-- Set plan cache behavior:
SET plan_cache_mode = force_custom_plan;

plan_cache_mode=auto는 generic plan과 custom plan 중에서 선택한다. force_custom_plan은 실행할 때마다 파라미터별 실행 계획을 생성한다(스니핑과 유사한 문제의 해결책).

MySQL

-- Server-side prepared statement:
PREPARE stmt FROM 'SELECT * FROM customer WHERE city = ?';
SET @city = 'Ankara';
EXECUTE stmt USING @city;
DEALLOCATE PREPARE stmt;

Prepared statement는 SQL 인젝션을 막고 파싱 비용을 낮춘다. MySQL은 드라이버 수준의 파라미터화도 지원한다.

SQL Server

-- Parameterized query (sp_executesql):
EXEC sp_executesql N'SELECT * FROM dbo.customer WHERE city = @city', N'@city nvarchar(50)', @city = N'Ankara';
-- Handle sniffing with a hint:
SELECT ... OPTION (RECOMPILE);
-- or OPTION (OPTIMIZE FOR (@city = 'Ankara'));

OPTION(RECOMPILE)은 실행할 때마다 파라미터별 실행 계획을 생성한다(CPU 비용이 큼). OPTIMIZE FOR는 특정/대표 값으로 실행 계획을 고정하며, OPTIMIZE FOR UNKNOWN은 평균 선택도를 사용한다.

MongoDB

// The query shape is the key of the plan cache:
db.customer.find({ city: "Ankara" }).explain("queryPlanner")
// Clear a stale plan:
db.customer.getPlanCache().clear()

같은 형태(같은 필드/연산자)의 쿼리는 캐시된 실행 계획을 공유하며, 리터럴 값이 달라도 새 실행 계획을 만들지 않는다. 값 분포가 크게 치우쳐 있으면 planCacheClear로 초기화한다.

Redis

# Not applicable: there is no query planner or parameter sniffing.

명령은 직접 실행된다. 파라미터화가 아니라 키 설계가 성능을 결정한다.

Elasticsearch

# Reuse the query with a parameterized search template:
POST _scripts/customer_city
{ "script": { "lang": "mustache", "source": { "query": { "term": { "city": "{{city}}" } } } } }
GET <index>/_search/template
{ "id": "customer_city", "params": { "city": "Ankara" } }

search template(Mustache)은 쿼리 본문을 파라미터화한다. 애플리케이션은 고정된 템플릿을 다른 값으로 호출하여 쿼리 일관성과 캐시 활용도를 높인다.

DBAtlas에서 열기 →