Amazon Neptune Gremlin의 쿼리 결과 캐싱 - Amazon Neptune

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

Amazon Neptune Gremlin의 쿼리 결과 캐싱

엔진 릴리스 1.0.5.1부터 Amazon Neptune은 Gremlin 쿼리에 대한 결과 캐시를 지원합니다.

쿼리 결과 캐시를 활성화한 다음 쿼리 힌트를 사용하여 Gremlin 읽기 전용 쿼리의 결과를 캐싱할 수 있습니다.

그런 다음 쿼리를 다시 실행하면 캐시에 있는 한 지연 시간이 짧고 I/O 비용 없이 캐싱된 결과가 검색됩니다. 이는 HTTP 엔드포인트와 Websockets를 사용하여 바이트 코드 또는 문자열 형식으로 제출된 쿼리에 적용됩니다.

참고

쿼리 캐시가 활성화된 경우에도 프로필 엔드포인트로 전송된 쿼리는 캐싱되지 않습니다.

여러 가지 방법으로 Neptune 쿼리 결과 캐시가 동작하는 방식을 제어할 수 있습니다. 예제:

  • 캐싱된 결과를 페이지를 지정한 블록 단위로 표시할 수 있습니다.

  • 지정된 쿼리에 대해 time-to-live(TTL)를 지정할 수 있습니다.

  • 지정된 쿼리의 캐시를 지울 수 있습니다.

  • 전체 캐시를 지울 수 있습니다.

  • 결과가 캐시 크기를 초과할 경우 알림을 받도록 설정할 수 있습니다.

캐시는 a least-recently-used(LRU) 정책을 사용하여 유지 관리됩니다. 즉, 캐시에 할당된 공간이 가득 차면 새 결과가 캐시될 때 공간을 확보하기 위해 least-recently-used 결과가 제거됩니다.

중요

t3.medium 또는 t4.medium 인스턴스 유형에서는 쿼리 결과 캐시를 사용할 수 없습니다.

Neptune에서 쿼리 결과 캐시 활성화

Neptune에서 쿼리 결과 캐시를 활성화하려면 콘솔을 사용하여 neptune_result_cache DB 인스턴스 파라미터를 1(활성화)로 설정합니다.

결과 캐시가 활성화되면 Neptune은 쿼리 결과를 캐싱하기 위해 현재 메모리의 일부를 따로 보관합니다. 사용하는 인스턴스 유형이 크고 사용 가능한 메모리가 많을수록 Neptune은 캐시에 더 많은 메모리를 할당합니다.

결과 캐시 메모리가 가득 차면 Neptune은 자동으로 least-recently-used(LRU) 캐시 결과를 삭제하여 새 결과를 처리합니다.

인스턴스 상태 명령을 사용하여 결과 캐시의 현재 상태를 확인할 수 있습니다.

힌트를 사용하여 쿼리 결과 캐시

쿼리 결과 캐시가 활성화되면 쿼리 힌트를 사용하여 쿼리 캐싱을 제어할 수 있습니다. 아래의 모든 예제는 동일한 쿼리 순회에 적용됩니다. 즉, 다음과 같습니다.

g.V().has('genre','drama').in('likes')

enableResultCache 사용하기

쿼리 결과 캐시가 활성화되면 다음과 같이 enableResultCache 쿼리 힌트를 사용하여 Gremlin 쿼리 결과를 캐싱할 수 있습니다.

g.with('Neptune#enableResultCache', true) .V().has('genre','drama').in('likes')

그러면 Neptune은 쿼리 결과를 반환하고 캐싱도 수행합니다. 나중에 정확히 동일한 쿼리를 다시 실행하여 캐싱된 결과에 액세스할 수 있습니다.

g.with('Neptune#enableResultCache', true) .V().has('genre','drama').in('likes')

캐싱된 결과를 식별하는 캐시 키는 쿼리 문자열 자체입니다. 즉, 다음과 같습니다.

g.V().has('genre','drama').in('likes')

enableResultCacheWithTTL 사용하기

enableResultCacheWithTTL 쿼리 힌트를 사용하여 쿼리 결과를 캐싱해야 하는 기간을 지정할 수 있습니다. 예를 들어, 다음 쿼리는 쿼리 결과가 120초 후에 만료되도록 지정합니다.

g.with('Neptune#enableResultCacheWithTTL', 120) .V().has('genre','drama').in('likes')

다시 말하지만, 캐싱된 결과를 식별하는 캐시 키는 기본 쿼리 문자열입니다.

g.V().has('genre','drama').in('likes')

또한 enableResultCache 쿼리 힌트와 함께 해당 쿼리 문자열을 사용하여 캐싱된 결과에 액세스할 수 있습니다.

g.with('Neptune#enableResultCache', true) .V().has('genre','drama').in('likes')

결과가 캐시된 후 120초 이상이 경과하면 해당 쿼리는 새 결과를 반환하고 any time-to-live 없이 캐시합니다.

enableResultCacheWithTTL 쿼리 힌트와 함께 동일한 쿼리를 다시 실행하여 캐싱된 결과에 액세스할 수도 있습니다. 예제:

g.with('Neptune#enableResultCacheWithTTL', 140) .V().has('genre','drama').in('likes')

120초가 경과할 때까지(즉, 현재 유효한 TTL) 쿼리 힌트를 사용하는이 새 enableResultCacheWithTTL 쿼리는 캐시된 결과를 반환합니다. 120초 후 새 결과를 반환하고 140초의 a time-to-live로 캐시합니다.

참고

쿼리 키에 대한 결과가 이미 캐시된 경우를 사용하는 동일한 쿼리 키는 새 결과를 생성enableResultCacheWithTTL하지 않으며 현재 캐시된 결과의 time-to-live에 영향을 주지 않습니다.

  • 이전에를 사용하여 결과를 캐시한 경우 enableResultCache가 새 결과를 enableResultCacheWithTTL 생성하고 지정한 TTL에 대해 캐시하기 전에 먼저 캐시를 지워야 합니다.

  • 이전에를 사용하여 결과를 캐싱한 경우 enableResultCachewithTTL가 새 결과를 enableResultCacheWithTTL 생성하고 지정한 TTL에 대해 결과를 캐싱하기 전에 이전 TTL가 먼저 만료되어야 합니다.

invalidateResultCacheKey 사용하기

invalidateResultCacheKey 쿼리 힌트를 사용하여 특정 쿼리 하나에 대해 캐싱된 결과를 지울 수 있습니다. 예제:

g.with('Neptune#invalidateResultCacheKey', true) .V().has('genre','drama').in('likes')

이 쿼리는 쿼리 키 g.V().has('genre','drama').in('likes')의 캐시를 지우고 해당 쿼리에 대한 새 결과를 반환합니다.

enableResultCache 또는 enableResultCacheWithTTLinvalidateResultCacheKey를 함께 사용할 수도 있습니다. 예를 들어, 다음 쿼리는 현재 캐싱된 결과를 지우고 새 결과를 캐싱하여 반환합니다.

g.with('Neptune#enableResultCache', true) .with('Neptune#invalidateResultCacheKey', true) .V().has('genre','drama').in('likes')

invalidateResultCache 사용하기

invalidateResultCache 쿼리 힌트를 사용하여 쿼리 결과 캐시에 있는 캐싱된 결과를 모두 지울 수 있습니다. 예제:

g.with('Neptune#invalidateResultCache', true) .V().has('genre','drama').in('likes')

이 쿼리는 전체 결과 캐시를 지우고 쿼리에 대한 새 결과를 반환합니다.

enableResultCache 또는 enableResultCacheWithTTLinvalidateResultCache를 함께 사용할 수도 있습니다. 예를 들어, 다음 쿼리는 전체 결과 캐시를 지우고 이 쿼리의 새 결과를 캐싱하여 반환합니다.

g.with('Neptune#enableResultCache', true) .with('Neptune#invalidateResultCache', true) .V().has('genre','drama').in('likes')

캐싱된 쿼리 결과 페이지 매김

다음과 같은 결과를 이미 대량으로 캐싱했다고 가정해 봅시다.

g.with('Neptune#enableResultCache', true) .V().has('genre','drama').in('likes')

이제 다음과 같은 범위 쿼리를 실행한다고 가정해 보겠습니다.

g.with('Neptune#enableResultCache', true) .V().has('genre','drama').in('likes').range(0,10)

Neptune은 먼저 전체 캐시 키(g.V().has('genre','drama').in('likes').range(0,10))를 찾습니다. 해당 키가 존재하지 않는 경우 Neptune은 다음으로 범위(g.V().has('genre','drama').in('likes'))가 없는 해당 쿼리 문자열에 키가 있는지 확인합니다. Neptune은 해당 키를 찾으면 범위에 지정된 대로 캐시에서 처음 10개의 결과를 가져옵니다.

참고

끝에 범위가 있는 쿼리에 invalidateResultCacheKey 쿼리 힌트를 사용하는 경우 Neptune은 범위가 있는 쿼리와 정확히 일치하는 항목을 찾지 못하면 범위가 없는 쿼리의 캐시를 지웁니다.

.iterate()와 함께 numResultsCached 사용

numResultsCached 쿼리 힌트를 사용하면 캐싱되는 모든 결과를 반환하지 않고 결과 캐시를 채울 수 있습니다. 이는 많은 결과를 페이지로 나누려는 경우에 유용할 수 있습니다.

numResultsCached 쿼리 힌트는 iterate()로 끝나는 쿼리에만 사용할 수 있습니다.

예를 들어, 샘플 쿼리의 처음 50개 결과를 캐싱하려는 경우는 다음과 같습니다.

g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 50) .V().has('genre','drama').in('likes').iterate()

이 경우 캐시의 쿼리 키는 g.with("Neptune#numResultsCached", 50).V().has('genre','drama').in('likes')입니다. 이제 다음 쿼리로 캐싱된 결과 중 처음 10개를 검색할 수 있습니다.

g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 50) .V().has('genre','drama').in('likes').range(0, 10)

또한 아래와 같이 쿼리에서 다음 10개 결과를 검색할 수 있습니다.

g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 50) .V().has('genre','drama').in('likes').range(10, 20)

잊지 말고 numResultsCached 힌트를 포함하세요. 이는 쿼리 키의 필수 부분이므로, 캐싱된 결과에 액세스하려면 반드시 있어야 합니다.

numResultsCached 사용 시 유의 사항
  • numResultsCached와 함께 제공하는 번호는 쿼리 끝에 적용됩니다.   예를 들어, 다음 쿼리가 실제로 캐싱되면 범위 (1000, 1500)이 됩니다.

    g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 500) .V().range(1000, 2000).iterate()
  • numResultsCached와 함께 제공하는 숫자는 캐싱할 최대 결과 수를 지정합니다.   예를 들어, 다음 쿼리가 실제로 캐싱되면 범위 (1000, 2000)이 됩니다.

    g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 100000) .V().range(1000, 2000).iterate()
  • .range().iterate()로 끝나는 쿼리에 의해 캐싱된 결과에는 고유한 범위가 있습니다.   예를 들어, 다음과 같은 쿼리를 사용하여 결과를 캐싱한다고 가정해 봅시다.

    g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 500) .V().range(1000, 2000).iterate()

    캐시에서 처음 100개의 결과를 검색하려면 다음과 같은 쿼리를 작성합니다.

    g.with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 500) .V().range(1000, 2000).range(0, 100)

    100개의 결과는 범위 (1000, 1100) 내 기본 쿼리의 결과와 동일합니다.

캐싱된 결과를 찾는 데 사용되는 쿼리 캐시 키

쿼리 결과가 캐싱된 후 동일한 쿼리 캐시 키를 사용하는 후속 쿼리는 새 쿼리를 생성하지 않고 캐시에서 결과를 검색합니다. 쿼리의 쿼리 캐시 키는 다음과 같이 평가됩니다.

  1. numResultsCached를 제외한 모든 캐시 관련 쿼리 힌트는 무시됩니다.

  2. 마지막 iterate() 단계는 무시됩니다.

  3. 나머지 쿼리는 바이트코드 표현에 따라 정렬됩니다.

결과 문자열을 캐시에 이미 있는 쿼리 결과의 인덱스와 비교하여 쿼리에 대한 캐시 적중 여부를 확인합니다.

다음 쿼리를 예로 들어 보겠습니다.

g.withSideEffect('Neptune#typePromotion', false).with("Neptune#enableResultCache", true) .with("Neptune#numResultsCached", 50) .V().has('genre','drama').in('likes').iterate()

이 파일은 다음과 같은 바이트코드 버전으로 저장됩니다.

g.withSideEffect('Neptune#typePromotion', false) .with("Neptune#numResultsCached", 50) .V().has('genre','drama').in('likes')

결과 캐시와 관련된 예외

이전에 캐싱된 모든 항목을 제거한 후에도 캐싱하려는 쿼리 결과가 너무 커서 캐시 메모리에 담을 수 없는 경우 Neptune에서 QueryLimitExceededException 오류가 발생합니다. 결과는 반환되지 않으며 예외로 인해 다음과 같은 오류 메시지가 생성됩니다.

The result size is larger than the allocated cache, please refer to results cache best practices for options to rerun the query.

다음과 같이 noCacheExceptions 쿼리 힌트를 사용하여 이 메시지를 숨길 수 있습니다.

g.with('Neptune#enableResultCache', true) .with('Neptune#noCacheExceptions', true) .V().has('genre','drama').in('likes')