쿼리 및 색인화 모범 사례 query-and-indexing-best-practices
AEM as a Cloud Service에서는 색인화와 관련된 모든 운영 측면이 자동화됩니다. 이를 통해 개발자는 효율적인 쿼리와 그에 해당하는 색인 정의를 생성하는 데 집중할 수 있습니다.
쿼리 사용 시기 when-to-use-queries
쿼리는 콘텐츠에 액세스하는 방법 중 하나이지만 유일한 방법인 것은 아닙니다. 많은 경우에서 기타 수단을 통해 더 효과적으로 저장소의 콘텐츠에 액세스할 수 있습니다. 해당되는 사용 사례에서 콘텐츠에 액세스할 수 있는 가장 효율적인 최선의 방법이 쿼리가 맞는지 고려해야 합니다.
저장소 및 분류법 디자인 repository-and-taxonomy-design
저장소 분류법을 디자인할 때 여러 가지 요인을 고려해야 합니다. 여기에는 액세스 제어, 지역화, 구성 요소 및 페이지 속성 상속 등이 포함됩니다.
이러한 우려사항을 고려한 분류법을 디자인하는 동안, 색인화 디자인의 "트래버스 가능성" 또한 고려하는 것이 중요합니다. 이 맥락에서 트래버스 가능성이란 콘텐츠가 그 경로에 따라 예측 가능한 방식으로 액세스될 수 있게 하는 분류법의 기능을 말합니다. 이는 여러 개의 쿼리를 실행해야 하는 시스템에 비해 유지 관리가 더 용이한 보다 효율적인 시스템을 완성합니다.
또한 분류법을 디자인할 때는 순서 지정 여부가 중요한지 고려해야 합니다. 명확한 순서 지정이 필요하지 않고 대량의 형제 노드가 예상되는 경우에는 sling:Folder
또는 oak:Unstructured
와 같은 비순차 노드 유형을 사용하는 것이 바람직합니다. 순서 지정이 필요한 경우에는 nt:unstructured
및 sling:OrderedFolder
가 더 적합할 것입니다.
구성 요소에서의 쿼리 queries-in-components
쿼리는 AEM 시스템에서 수행하는 비교적 더 까다로운 작업들 중 하나일 수 있기 때문에 구성 요소에서는 이를 피하는 것이 좋습니다. 페이지가 렌더링될 때마다 여러 쿼리가 실행되도록 할 경우 종종 시스템 성능이 저하될 수 있습니다. 구성 요소 렌더링 시 쿼리 실행을 피하는 데 이용할 수 있는 전략은 두 가지로, 노드 트래버스 전략과 결과 프리페치 전략입니다.
노드 트래버스 traversing-nodes
필요한 데이터의 위치에 대한 사전 지식이 가능한 방식으로 저장소를 디자인한 경우 쿼리를 실행하여 찾을 필요 없이 필요한 경로에서 이 데이터를 검색하는 코드를 배포할 수 있습니다.
예를 들어 특정 카테고리에 부합하는 콘텐츠를 렌더링하는 경우가 있습니다. 한 가지 접근법은 카테고리에서 항목을 표시하는 구성 요소를 채우도록 쿼리할 수 있는 카테고리 속성을 가진 콘텐츠를 구성하는 것입니다.
그보다 나은 접근법은 이 콘텐츠를 카테고리별 분류법에 따라 구성하여 수동으로 가져올 수 있도록 하는 것입니다.
예를 들어 콘텐츠가 다음과 유사한 분류법으로 저장된다고 가정해봅시다.
/content/myUnstructuredContent/parentCategory/childCategory/contentPiece
/content/myUnstructuredContent/parentCategory/childCategory
노드를 간편하게 가져올 수 있으며, 그 자식 항목들은 구문 분석되어 구성 요소 렌더링에 사용될 수 있습니다.
또한 작은 크기 또는 같은 형식의 결과 세트를 다룰 때, 동일한 결과 세트를 반환하는 쿼리를 만드는 것보다 저장소를 트래버스하고 필요한 노드를 모으는 것이 더 빠를 수 있습니다. 일반적인 고려사항은 가능하면 쿼리를 피하는 것입니다.
결과 프리페치 prefetching-results
가끔 콘텐츠나 구성 요소에 관한 요구 사항 때문에, 필요 데이터를 가져오는 방법으로 노드 트래버스를 사용할 수 없는 경우가 있습니다. 이 경우, 구성 요소가 렌더링되기 전에 필요 쿼리를 실행해야 최적의 성능을 보장할 수 있습니다.
구성 요소에 필요한 결과를 구성 요소 제작 당시에 계산할 수 없고 콘텐츠가 변경될 것으로 예상되지 않는 상황에서는 변경이 이루어진 후에 쿼리를 실행할 수 있습니다.
데이터나 콘텐츠가 규칙적으로 변경되는 경우에는 일정에 따라 쿼리를 실행하거나 기반 데이터의 업데이트에 대한 리스너를 사용하여 쿼리를 실행할 수 있습니다. 그러면 저장소의 공유 위치에 결과를 작성할 수 있습니다. 이 경우, 런타임 시 쿼리를 실행할 필요 없이 이 데이터를 필요로 하는 모든 구성 요소가 이 단일 노드에서 해당 값을 가져올 수 있습니다.
시작 시에 채워지고 변경사항이 적용될 때마다 업데이트되는 인메모리 캐시 결과를 보관할 때도 이와 유사한 전략을 사용할 수 있습니다(JCR ObservationListener
또는 Sling ResourceChangeListener
사용).
쿼리 최적화 optimizing-queries
Oak 문서는 쿼리 실행 방식에 대한 높은 수준의 개요를 제공합니다. 이는 본 문서에서 설명하는 모든 최적화 활동의 기반을 구성합니다.
AEM as a Cloud Service은 효율적인 쿼리 구현을 지원하도록 설계된 쿼리 성능 도구를 제공합니다.
- 이 도구는 이미 실행된 쿼리를 그 관련 성능 특성 및 쿼리 계획과 함께 표시합니다.
- 이 도구를 사용하면 단순히 쿼리 플랜을 표시하는 것부터 전체 쿼리를 실행하는 것까지 다양한 수준에서 애드혹 쿼리를 수행할 수 있습니다.
쿼리 성능 도구는 Cloud Manager의 개발자 콘솔을 통해 접근 가능합니다. AEM as a Cloud Service의 쿼리 성능 도구는 AEM 6.x 이상 버전에서의 쿼리 실행에 관한 세부 정보를 제공합니다.
이 차트는 쿼리 최적화를 위해 쿼리 성능 도구를 사용하는 일반적인 흐름을 설명합니다.
색인 사용 use-an-index
모든 쿼리는 최적의 성능을 제공하기 위해 색인을 사용해야 합니다. 대다수의 경우 기존의 기본 제공 색인으로 충분히 쿼리를 처리할 수 있습니다.
가끔은 기존 색인에 사용자 정의 속성을 추가하여, 색인을 사용해 추가적인 제한을 쿼리할 수 있습니다. 자세한 내용은 콘텐츠 검색 및 색인화 문서를 참조하십시오. 이 문서의 JCR 쿼리 치트시트 섹션에서는 특정 쿼리 형식을 지원하기 위해 인덱스의 속성 정의를 찾는 방법에 대해 설명합니다.
올바른 기준 사용 use-the-right-criteria
모든 쿼리에 대한 주 제한은 속성 일치여야 합니다. 이것이 가장 효율적인 유형이기 때문입니다. 부가적인 속성 제한을 추가하면 결과가 더욱 제한됩니다.
쿼리 엔진은 단일 색인만 고려합니다. 즉, 더 많은 사용자 정의 색인 속성을 추가하여 기존 색인을 사용자 정의하는 것이 가능하고 필요하다는 의미입니다.
이 문서의 JCR 쿼리 치트시트 섹션에는 사용 가능한 제한이 나열되어 있으며 색인 정의가 선택되려면 어떤 형태여야 하는지 설명합니다. 쿼리 성능 도구를 사용하여 쿼리를 테스트할 수 있으며 올바른 색인이 사용되었는지 및 쿼리 엔진이 색인 외의 제한을 평가할 필요는 없는지 확인할 수 있습니다.
순서 지정 ordering
결과의 특정한 순서가 필요하다면 쿼리 엔진에서 두 가지 방법으로 이를 구성할 수 있습니다.
-
색인이 결과를 완전하게 올바른 순서에 따라 제공할 수 있습니다.
- 이는 색인 정의에서 순서 지정에 사용되는 속성에
ordered=true
주석이 추가될 경우 가능합니다.
- 이는 색인 정의에서 순서 지정에 사용되는 속성에
-
쿼리 엔진이 순서 지정 프로세스를 수행합니다.
- 이는 쿼리 엔진이 색인 외에서 필터링을 수행하거나 순서 지정 속성에
ordered=true
속성 주석이 추가되어 있지 않은 경우 발생할 수 있습니다. - 이 경우, 정렬을 위해 메모리에서 완전한 결과 세트를 읽어야 하며 이는 첫 번째 방법보다 훨씬 속도가 더딥니다.
- 이는 쿼리 엔진이 색인 외에서 필터링을 수행하거나 순서 지정 속성에
결과 크기 제한 restrict-result-size
쿼리 결과를 가져온 크기는 쿼리 수행에 있어 중요한 요인입니다. 결과는 소극적 방식으로 가져오게 되기 때문에, 단순히 첫 20개 결과를 가져오는 것과 10,000개 결과를 가져오는 것은 런타임과 메모리 사용량 모두의 측면에서 차이가 있습니다.
이는 또한 모든 결과를 가져오는 경우에만 결과 세트의 크기를 정확하게 측정할 수 있다는 의미입니다. 이러한 이유로 인해, 쿼리를 보강(자세한 내용은 본 문서의 JCR 쿼리 치트시트 섹션 참조)하거나 결과 읽기를 제한하여, 가져온 결과 세트는 항상 제한해야 합니다.
이러한 제한은 쿼리 엔진이 100,000노드의 트래버스 제한 에 도달하는 것 또한 예방합니다. 이 제한에 도달하면 쿼리가 강제 정지됩니다.
잠재적으로 크기가 큰 결과 집합을 완전히 처리해야 하는 경우 이 문서의 결과 집합이 큰 쿼리 섹션을 참조하십시오.
쿼리 성능 도구 query-performance-tool
쿼리 성능 도구(/libs/granite/operations/content/diagnosistools/queryPerformance.html
에 있으며 Cloud Manager의 Developer Console를 통해 사용 가능)는 다음을 제공합니다.
- 현재 5000개 이상의 행을 읽기/스캔하는 쿼리로 정의된 '느린 쿼리' 목록입니다.
- '자주 사용하는 쿼리' 목록
- Oak에서 특정 쿼리를 실행하는 방법을 이해하는 '쿼리 설명' 도구입니다.
"느린 쿼리" 및 "자주 찾는 쿼리" 테이블에는 다음이 포함됩니다.
-
쿼리 문 자체입니다.
-
쿼리를 실행하는 페이지 또는 애플리케이션 기능을 식별할 수 있도록 쿼리를 실행한 마지막 스레드의 세부 정보입니다.
-
쿼리에 대한 '읽기 최적화' 점수.
- 이는 쿼리를 실행하기 위해 스캔한 행/노드 수와 일치하는 결과 읽기 수 간의 비율로 계산됩니다.
- 인덱스에서 모든 제한(및 순서 지정)을 처리할 수 있는 쿼리는 일반적으로 90% 이상을 받습니다.
-
최대 행 수 세부 정보 -
- 읽기 - 행이 결과 세트의 일부로 포함되었음을 나타냅니다.
- 스캔됨 - 행이 기본 색인 쿼리의 결과(색인화된 쿼리의 경우)에 포함되었거나 노드 저장소(저장소 순회의 경우)에서 읽혔음을 나타냅니다.
이러한 테이블은 완전히 인덱싱되지 않은 쿼리를 식별하는 데 도움이 됩니다(인덱스 사용 참조) 또는 너무 많은 노드를 읽는 중입니다(저장소 트래버스 및 인덱스 트래버스 참조). 이러한 쿼리는 빨간색으로 표시된 적절한 관심 영역을 사용하여 강조 표시됩니다.
Reset Statistics
옵션은 테이블에서 수집된 모든 기존 통계를 제거하는 데 제공됩니다. 이렇게 하면 애플리케이션 자체 또는 쿼리 설명 도구를 통해 특정 쿼리를 실행하고 실행 통계를 분석할 수 있습니다.
쿼리 설명
쿼리 설명 도구를 사용하면 개발자가 쿼리를 실행할 때 사용된 인덱스에 대한 세부 정보를 포함하여 쿼리 실행 계획을 이해할 수 있습니다(쿼리 실행 계획 읽기 참조). 쿼리를 색인화하여 성능을 예측하거나 소급하여 분석하는 방법을 이해하는 데 사용할 수 있습니다.
쿼리 설명
쿼리를 설명하려면 다음 작업을 수행하십시오.
-
Language
드롭다운 목록을 사용하여 적절한 쿼리 언어를 선택하십시오. -
Query
필드에 쿼리 문을 입력합니다. -
필요한 경우 제공된 확인란을 사용하여 쿼리가 실행되는 방법을 선택합니다.
-
기본적으로 JCR 쿼리는 쿼리 실행 계획을 식별하기 위해 실행할 필요가 없습니다(QueryBuilder 쿼리의 경우 아님).
-
쿼리 실행을 위한 세 가지 옵션이 제공됩니다.
Include Execution Time
- 쿼리를 실행하지만 결과를 읽지 않습니다.Read first page of results
- 쿼리를 실행하고 20개의 결과 중 첫 번째 '페이지'를 읽습니다(쿼리 실행에 대한 모범 사례를 복제합니다).Include Node Count
- 쿼리를 실행하고 전체 결과 집합을 읽습니다(일반적으로 권장되지 않음 - 인덱스 순회 참조).
-
쿼리 설명 팝업 query-explanation-popup
Explain
을(를) 선택하면 쿼리 설명(및 선택한 경우 실행) 결과를 설명하는 팝업이 사용자에게 표시됩니다.
이 팝업에는 -에 대한 세부 사항이 포함됩니다.
- 쿼리를 실행할 때 사용되는 색인입니다(또는 저장소 순회을 사용하여 쿼리를 실행할 경우 색인이 없음).
- 실행 시간(
Include Execution Time
확인란이 선택된 경우) 및 읽은 결과 수(Read first page of results
또는Include Node Count
확인란이 선택된 경우). - 실행 계획을 통해 쿼리 실행 방법을 자세히 분석할 수 있습니다. 해석 방법은 쿼리 실행 계획 읽기를 참조하십시오.
- 처음 20개 쿼리 결과의 경로(
Read first page of results
확인란이 선택된 경우) - 이 쿼리를 실행하기 위해 고려된 인덱스의 상대적 비용을 보여주는 쿼리 계획의 전체 로그(비용이 가장 낮은 인덱스가 선택됨).
쿼리 실행 계획 읽기 reading-query-execution-plan
쿼리 실행 계획에는 특정 쿼리의 성능을 예측(또는 설명)하는 데 필요한 모든 것이 포함되어 있습니다. 원래 JCR(또는 Query Builder) 쿼리의 제한 사항 및 순서를 기본 색인(Lucene, Elastic 또는 Property)에서 실행된 쿼리와 비교하여 쿼리가 얼마나 효율적으로 실행되는지 이해합니다.
다음 쿼리를 고려하십시오.
/jcr:root/content/dam//element(*, dam:Asset) [jcr:content/metadata/dc:title = "My Title"] order by jcr:created
…다음 포함: -
-
3개 제한 사항
- Nodetype(
dam:Asset
) - 경로(
/content/dam
의 하위 항목) - 속성(
jcr:content/metadata/dc:title = "My Title"
)
- Nodetype(
-
jcr:created
속성으로 순서 지정
이 쿼리를 설명하면 다음 플랜이 생성됩니다.
[dam:Asset] as [a] /* lucene:damAssetLucene-9(/oak:index/damAssetLucene-9) +:ancestors:/content/dam +jcr:content/metadata/dc:title:My Title ordering:[{ propertyName : jcr:created, propertyType : UNDEFINED, order : ASCENDING }] where ([a].[jcr:content/metadata/dc:title] = 'My Title') and (isdescendantnode([a], [/content/dam])) */
이 플랜 내에서 기본 색인에서 실행되는 쿼리를 설명하는 섹션은 -
lucene:damAssetLucene-9(/oak:index/damAssetLucene-9) +:ancestors:/content/dam +jcr:content/metadata/dc:title:My Title ordering:[{ propertyName : jcr:created, propertyType : UNDEFINED, order : ASCENDING }]
플랜의 이 섹션에서는 다음을 명시합니다. -
-
색인은 이 쿼리를 실행하는 데 사용됩니다.
- 이 경우 Lucene 인덱스
/oak:index/damAssetLucene-9
이(가) 사용되므로 나머지 정보는 Lucene 쿼리 구문에 있습니다.
- 이 경우 Lucene 인덱스
-
3가지 제한 사항은 모두 색인에 의해 처리됩니다.
- 노드 유형 제한
damAssetLucene-9
은(는) dam:Asset 유형의 노드만 인덱싱하므로 암시적입니다.
- 경로 제한
+:ancestors:/content/dam
이(가) Lucene 쿼리에 표시되기 때문입니다.
- 속성 제한
+jcr:content/metadata/dc:title:My Title
이(가) Lucene 쿼리에 표시되기 때문입니다.
- 노드 유형 제한
-
순서는 색인에 의해 처리됩니다.
ordering:[{ propertyName : jcr:created, propertyType : UNDEFINED, order : ASCENDING }]
이(가) Lucene 쿼리에 표시되기 때문입니다.
색인 쿼리에서 반환된 결과는 액세스 제어 필터링 외에 쿼리 엔진에서 더 이상 필터링되지 않으므로 이러한 쿼리는 잘 수행될 수 있습니다. 그러나 모범 사례를 따르지 않는 경우 이러한 쿼리가 계속 느리게 실행될 수 있습니다. 아래 인덱스 순회를 참조하십시오.
다른 쿼리 고려 -
/jcr:root/content/dam//element(*, dam:Asset) [jcr:content/metadata/myProperty = "My Property Value"] order by jcr:created
…다음 포함: -
-
3개 제한 사항
- Nodetype(
dam:Asset
) - 경로(
/content/dam
의 하위 항목) - 속성(
jcr:content/metadata/myProperty = "My Property Value"
)
- Nodetype(
-
jcr:created
속성별 순서 지정**
이 쿼리를 설명하면 다음 플랜이 생성됩니다.
[dam:Asset] as [a] /* lucene:damAssetLucene-9-custom-1(/oak:index/damAssetLucene-9-custom-1) :ancestors:/content/dam ordering:[{ propertyName : jcr:created, propertyType : UNDEFINED, order : ASCENDING }] where ([a].[jcr:content/metadata/myProperty] = 'My Property Value') and (isdescendantnode([a], [/content/dam])) */
이 플랜 내에서 기본 색인에서 실행되는 쿼리를 설명하는 섹션은 -
lucene:damAssetLucene-9(/oak:index/damAssetLucene-9) :ancestors:/content/dam ordering:[{ propertyName : jcr:created, propertyType : UNDEFINED, order : ASCENDING }]
플랜의 이 섹션에서는 다음을 명시합니다. -
-
3개 중 2개의 제한만 색인에 의해 처리됩니다.
- 노드 유형 제한
damAssetLucene-9
은(는) dam:Asset 유형의 노드만 인덱싱하므로 암시적입니다.
- 경로 제한
+:ancestors:/content/dam
이(가) Lucene 쿼리에 표시되기 때문입니다.
- 노드 유형 제한
-
속성 제한
jcr:content/metadata/myProperty = "My Property Value"
이(가) 인덱스에서 실행되지 않고 기본 Lucene 쿼리 결과에 대한 쿼리 엔진 필터링으로 적용됩니다.- 이 속성은 이 쿼리에 사용된
damAssetLucene-9
인덱스에서 인덱싱되지 않으므로+jcr:content/metadata/myProperty:My Property Value
이(가) Lucene 쿼리에 표시되지 않기 때문입니다.
- 이 속성은 이 쿼리에 사용된
이 쿼리 실행 계획을 수행하면 인덱스에서 /content/dam
아래의 모든 에셋을 읽은 다음 쿼리 엔진에 의해 추가로 필터링됩니다(결과 집합에 인덱싱되지 않은 속성 제한과 일치하는 에셋만 포함됨).
자산 중 극히 일부만 제한 jcr:content/metadata/myProperty = "My Property Value"
과(와) 일치하더라도 쿼리는 요청된 '페이지'의 결과를 채우려면(시도) 많은 수의 노드를 읽어야 합니다. 이로 인해 쿼리가 제대로 수행되지 않을 수 있으며, 이는 [쿼리 성능 도구]에서 낮은 Read Optimization
점수로 표시되며 많은 수의 노드가 순회되고 있음을 나타내는 WARN 메시지가 나타날 수 있습니다(인덱스 순회 참조).
이 두 번째 쿼리의 성능을 최적화하려면 damAssetLucene-9
인덱스의 사용자 지정 버전(damAssetLucene-9-custom-1
)을 만들고 다음 속성 정의를 추가하십시오.
"myProperty": {
"jcr:primaryType": "nt:unstructured",
"propertyIndex": true,
"name": "jcr:content/metadata/myProperty"
}
JCR 쿼리 치트 시트 jcr-query-cheatsheet
효율적인 JCR 쿼리 및 색인 정의를 생성하는 데 도움을 얻고 싶다면 JCR 쿼리 치트시트를 다운로드하여 개발 중 참조할 수 있습니다.
여기에는 쿼리 성능이 다양한 여러 시나리오를 포괄하는 QueryBuilder, XPath, SQL-2에 대한 샘플 쿼리가 포함되어 있습니다. 이 치트시트는 또한 Oak 색인을 구축하거나 사용자 정의하는 방법에 대한 권장 사항도 제공합니다. 이 치트시트의 콘텐츠는 AEM as a Cloud Service 및 AEM 6.5에 적용됩니다.
색인 정의 우수 사례 index-definition-best-practices
다음은 인덱스를 정의하거나 확장할 때 고려해야 할 몇 가지 모범 사례입니다.
-
기존 인덱스(예:
dam:Asset
또는cq:Page
)가 있는 노드 유형의 경우 새 인덱스를 추가하는 것보다 OOTB 인덱스 확장을 선호합니다.dam:Asset
노드 유형에 새 인덱스(특히 전체 텍스트 인덱스)를 추가하는 것은 권장되지 않습니다(이 참고 참조).
-
새 인덱스를 추가할 때
- 항상 'lucene' 유형의 인덱스를 정의하십시오.
- 인덱스 정의(및 관련 쿼리)와
selectionPolicy = tag
에서 인덱스 태그를 사용하여 인덱스가 의도한 쿼리에만 사용되는지 확인하십시오. queryPaths
과(와)includedPaths
이(가) 모두 제공되었는지 확인합니다(일반적으로 동일한 값 사용).- 유용한 결과를 포함하지 않을 경로를 제외하려면
excludedPaths
을(를) 사용하십시오. - 필요한 경우에만
analyzed
속성을 사용합니다. 예를 들어 해당 속성에만 대해 전체 텍스트 쿼리 제한을 사용해야 할 경우입니다. - 항상
async = [ async, nrt ]
,compatVersion = 2
및evaluatePathRestrictions = true
을(를) 지정하십시오. - nodescope 전체 텍스트 인덱스가 필요한 경우에만
nodeScopeIndex = true
을(를) 지정하십시오.
자동화된 Cloud Manager 파이프라인 확인은 위에서 설명한 몇 가지 모범 사례를 적용합니다.
결과 세트 크기가 큰 쿼리 queries-with-large-result-sets
결과 세트 크기가 큰 쿼리는 피하는 것이 바람직하지만 이러한 결과 세트를 꼭 처리해야 하는 경우도 존재합니다. 결과의 크기를 정확하게 알 수 없는 경우가 많기 때문에 신뢰성 있는 처리를 위해서는 몇 가지 예방 조치를 실시해야 합니다.
- 쿼리는 요청 내에서 실행해서는 안 됩니다. 대신, Sling Job이나 AEM 워크플로의 일부로서 쿼리를 실행해야 합니다. 이 두 방법은 총 런타임에 제한이 전혀 없으며, 쿼리와 그 결과를 처리하는 동안 인스턴스가 정지되면 재시작됩니다.
- 100,000노드의 쿼리 제한을 극복하려면 키세트 페이지 매김의 사용을 고려해야 하며 쿼리를 다양한 하위 쿼리로 분할해야 합니다.
저장소 트래버스 repository-traversal
저장소를 트래버스하는 쿼리는 색인을 사용하지 않으며 다음과 유사한 메시지를 사용해 기록합니다.
28.06.2022 13:32:52.804 *WARN* [127.0.0.1 [1656415972414] POST /libs/settings/granite/operations/diagnosis/granite_queryperformance.explain.json HTTP/1.1] org.apache.jackrabbit.oak.plugins.index.Cursors$TraversingCursor Traversed 98000 nodes with filter Filter(query=select [jcr:path], [jcr:score], * from [nt:base] as a /* xpath: //* */, path=*) called by com.adobe.granite.queries.impl.explain.query.ExplainQueryServlet.getHeuristics; consider creating an index or changing the query
이러한 로그 스니펫을 통해 다음을 파악할 수 있습니다.
- 쿼리 자체:
//*
- 이 쿼리를 실행한 Java 코드: 쿼리 생성자를 식별하도록 도와주는
com.adobe.granite.queries.impl.explain.query.ExplainQueryServlet::getHeuristics
.
이 정보가 있으면 본 문서의 쿼리 최적화 섹션에 설명된 방법으로 이 쿼리를 최적화할 수 있습니다.
색인 순회 index-traversal
인덱스를 사용하지만 여전히 많은 노드를 읽는 쿼리는 다음과 유사한 메시지로 기록됩니다(Traversed
이(가) 아닌 Index-Traversed
용어 참고).
05.10.2023 10:56:10.498 *WARN* [127.0.0.1 [1696502982443] POST /libs/settings/granite/operations/diagnosis/granite_queryperformance.explain.json HTTP/1.1] org.apache.jackrabbit.oak.plugins.index.search.spi.query.FulltextIndex$FulltextPathCursor Index-Traversed 60000 nodes with filter Filter(query=select [jcr:path], [jcr:score], * from [dam:Asset] as a where isdescendantnode(a, '/content/dam') order by [jcr:content/metadata/unindexedProperty] /* xpath: /jcr:root/content/dam//element(*, dam:Asset) order by jcr:content/metadata/unindexedProperty */, path=/content/dam//*)
이 문제는 다음과 같은 여러 가지 이유로 발생할 수 있습니다.
-
쿼리의 모든 제한을 색인에서 처리할 수 있는 것은 아닙니다.
- 이 경우, 최종 결과 세트의 상위 집합은 색인에서 읽히고 이어서 쿼리 엔진에서 필터링됩니다.
- 이는 기본 색인 쿼리에 제한을 적용하는 것보다 몇 배 더 느립니다.
-
쿼리는 인덱스에서 'ordered'로 표시되지 않은 속성별로 정렬됩니다.
- 이 경우 인덱스에서 반환된 모든 결과는 쿼리 엔진에서 읽고 메모리 내에서 정렬해야 합니다.
- 이는 기본 색인 쿼리에서 정렬을 적용하는 것보다 몇 배 더 느립니다.
-
쿼리 실행자가 큰 결과 집합을 반복하려고 합니다.
- 이 상황은 다음과 같은 몇 가지 이유로 발생할 수 있습니다.
p.guessTotal
의 생략(또는 매우 큰 guessTotal 사용)으로 인해 QueryBuilder에서 계산 결과를 계산하는 많은 결과를 반복하게 됨p.guessTotal
에 적절한 값을 제공하십시오.p.limit=-1
)에서 크거나 제한되지 않은 제한 사용p.limit
에 적절한 값 사용(1000 이하)