4

couchbase 쿼리 플랜의 작동 방식을 이해하는 데 문제가 있습니다. Couchbase 4.1에서 SpringData를 사용하고 Couchbase 저장소의 사용자 정의 구현을 제공한다. 카우치베이스 주식회사 저장소의 내 사용자 지정 implememtnation 내부 내가 방법을 아래에있다 : 결과에서Couchbase는 N1QL 매개 변수화 된 쿼리와 함께 잘못된 인덱스를 사용합니다.

String queryAsString = "SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS FROM MyDatabase WHERE segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1"; 
JsonObject params = JsonObject.create() 
     .put(CLASS_VARIABLE, MyClass.class.getCanonicalName()) 
     .put(ID_VARIABLE, segmentId); 

N1qlQuery query = N1qlQuery.parameterized(queryAsString, params); 
List<MyClass> resultList = couchbaseTemplate.findByN1QL(query, SegmentMembers.class); 
return resultList.isEmpty() ? null : resultList.get(0); 

, 봄의 데이터는 다음과 같은 JSON 객체는 카우치베이스 주식회사에 질의 표현이 생성

{ 
    "$class":"path/MyClass", 
    "statement":"SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS from MyDatabase where segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1", 
    "id":"6592c16a-c8ae-4a74-bc17-7e18bf73b3f8" 
} 

을 그리고 그 문제는 내가 실행할 때 성능입니다 그것은 Java와 N1QL Rest API 또는 cbq 콘솔을 통해 가능합니다. 이 쿼리를 cbq에서 실행하려면 매개 변수 참조를 정확한 값으로 바꾸기 만하면됩니다.

select 문 앞에 EXPLAIN 절을 추가 한 후에 다른 실행 계획을 언급했습니다. 이 쿼리를 Java Spring 데이터 또는 N1QL Rest API를 통해 매개 변수화 된 쿼리로 실행합니다.이 쿼리에서는이 경우에 대해 정확하게 만든 인덱스를 사용하지 않는다고 언급했습니다. 인덱스 definiton 아래 찾을 수 있습니다 나는 CBQ의 CONSOL를 통해 쿼리를 실행할 때

CREATE INDEX `testMembers` ON MyDatabase `m`(`_class`,`segmentId`,`executionTime`) WHERE (`_class` = "path/MyClass") USING GSI; 

그래서, 카우치베이스 주식회사 내 idnex를 사용하여 쿼리 성능이 매우 좋다. 하지만 N1QL 나머지 API 또는 자바를 통해이 쿼리를 실행할 때 해당 쿼리가 내 인덱스를 사용하지 않는 것을 볼 수 있습니다. 이 사실을 증명하는 실행 계획의 일부 찾을 수 아래 : 그래서

"~children": [ 
{ 
    "#operator": "PrimaryScan", 
    "index": "#primary", 
    "keyspace": "CSM", 
    "namespace": "default", 
    "using": "gsi" 
}, 

을, 문제는 그 오른쪽 카우치베이스 주식회사 쿼리 최적화 프로그램의 법적 행동은? 쿼리 계획이 매개 변수의 실제 값을 고려하지 않는다는 뜻입니까? 그리고 수동으로 쿼리 문자열에 값을 넣거나 N1Ql 매개 변수가있는 쿼리와 올바른 인덱스 선택을 사용하는 다른 방법이 있습니까? 샤시 주권 대답 매개 변수 N1QL 질의에 내가 추가 N1qlParams.build(). 애드혹 (false)를 매개 변수에 따라 편집

. 이 쿼리는 여전히 성능 문제가 있으므로 내 문제가 해결되지 않습니다. 또한 쿼리를 인쇄 할 때 앞에서 설명한 것과 동일하다는 것을 알 수 있습니다. 그래서, 내 쿼리는 여전히 잘못 분석하고 성능 저하를 유발합니다.

+0

이 문제가 해결되었는지 Couchbase 4.5.1을 사용해 볼 수 있습니까? – geraldss

+0

아니요, 4.6에서도 수정되지 않았습니다 – gaperton

+0

그리고 분명히 해결할 부분이 없습니다. :) 아래 내 대답을 참조하십시오. – gaperton

답변

1

문제는 'where'절이 WHERE (_class = "path/MyClass") 인 색인이 있고 동시에 쿼리에서 매개 변수로 _class을 전달했기 때문에 발생합니다.

따라서 매개 변수화 된 쿼리를 분석하는 쿼리 최적화 프로그램은이 쿼리가 _class = "path/MyClass"에 대해 생성 된 인덱스를 사용할 수 없다는 것을 알지 못합니다. 원인은 선택 위치 인 _class = $class입니다. 아주 간단하고 맞습니까?

따라서 색인의 'where'를 선택 매개 변수로 언급 한 필드는 전달하지 마십시오. 대신, create index과 동일한 방법으로 선택 항목에 _class = "path/MyClass"을 입력하십시오. 그리고 모든 것이 잘되어야합니다.

여기 couchbase 이슈 추적 시스템의 티켓이 있습니다.

https://issues.couchbase.com/browse/MB-22185?jql=text%20~%20%22parameters%20does%20not%20use%20index%22

2

당신이 쿼리가 전달되어야 작동 방법 N1QL 매개 변수화 된 쿼리 알아야 할 모든의 첫째 :

String query= select * from bucketName where _class=$_class and segmentId=$segmentId LIMIT $limit ; 

지금 쿼리로 전달해야합니다

N1QL.parameterized(query,jsonObject,N1qlParams.build().adhoc(false)); 

하는 jsonObject이이 곳의 모든 자리 표시 자 값. 당신이 당신의 쿼리가 그것을 사용할 것이다 최적화하려면 이후

JsonObject jsonObject=JsonObject.create().put("_class","com.entity,user").put("segmentId","12345").put("limit",100); 

N1qlParams.build().adhoc(false)는 선택 사항입니다. 그것은 이전에 입력 된 쿼리를 추적하고 LRU를 사용하여 LRU를 사용하며 다음에 쿼리를 구문 분석 할 필요가 없도록 미리 준비된 문으로 이전의 쿼리를 페치 할 필요가 없도록 레코드를 유지합니다.

유일한 문제는 couchbase가 마지막 5000 개의 레코드 만 쿼리합니다.

+0

죄송합니다, 그러나 이것은 내 문제를 해결하지 못했습니다. 나는이 플래그를 false로 설정하여 쿼리를 생성하더라도 여전히 성능 문제가 있습니다. 다른 제안 사항이 있으십니까? – 4the3eam

+0

커버 인덱스를 사용해보십시오. 대부분의 성능 문제를 해결합니다. 5 개의 속성을 사용하여 쿼리하려는 경우 인덱스를 생성하는 동안 해당 속성을 지정하십시오. –

+0

쿼리 n Json 객체의 변수 작성이 동일해야합니다. 그렇지 않으면 작동하지 않습니다. –