2016-08-09 35 views
8

Mit Couchbase-Server 4.1.0 (und 4.5), Java SDK 2.2.8 (auch mit 2.2.7, 2.3.1, & 2.3.3 versucht), habe ich eine Abfrage Nutzung eines sekundären Index, der gut läuft, wenn ich meinen Code lokal und sogar über CBQ (CBQ dauert etwa 3 ms) auf dem AWS-Server laufen. Wenn ich meine App auf AWS ausführe, erhalte ich jedoch eine TimeOutException und es ist nur eine Abfrage, die ausläuft, andere nicht. Siehe Details unten.N1QL Abfrage Timeout bei Verwendung der parametrisierten IN-Klausel

Kann erwähnenswert sein mein Couchbase-Setup hat 3 Eimer.

Beispiel Doc:

"bucketName": { 
    "userName": "User_A", 
    "MessageContent": "This is a message", 
    "docType": "msg", 
    "ParentMsgId": "1234", 
    "MsgType": "test", 
    "expireTimestamp": 1454975772613, 
    "publishTimestamp": 1455322362028, 
    "id": "145826845", 
    "urls": [], 
    "subject": "this is a subject", 
    "type": 1, 
    "GroupId": "Group_1" 
} 

Sekundärindex:

CREATE INDEX `indexName` ON `bucketName`(`ParentMsgId`,`docType`,`publishTimestamp`) USING GSI 

Beispiel Abfrage von N1qlQuery#n1ql() extrahiert

{"statement": 
"select count(*) as msgCount from bucketName 
where ParentMsgId is not missing and docType = 'msg' 
and ParentMsgId IN $parentId 
and publishTimestamp between $startTime and $endTime 
","$endTime":1470726861816, 
    "$startTime":1470640461816, 
    "$parenIds":["fa11845b-9ea5-4778-95fe-e7206843c69b"] 
} 

Java-Code

public static final String COUNT_STATEMENT = "select count(*) as count " + 
      "from bucketName " + 
      "where ParentMsgId is not missing " + 
      "and docType = 'msg' " + 
      "and ParentMsgId IN $parentIds " + 
      "and publishTimestamp between $startTime and $endTime"; 

public int getCountForDuration(Long startTime, Long endTime, Collection<String> parentIds){ 
    List<String> idList = new ArrayList<>(parentIds); 
    JsonObject placeHolders = JsonObject.create() 
             .put("parentIds", JsonArray.from(idList)) 
             .put("startTime", startTime) 
             .put("endTime", endTime); 
    N1qlQuery query = N1qlQuery.parameterized(COUNT_STATEMENT, placeHolders)    
    N1qlQueryResult result = bucket.query(query); 
    ... 
} 

Abfrage Erklären Ergebnis

cbq> explain select count(*) as msgCount from bucketName where ParentMsgId is not missing and docType = 'msg' and ParentMsgId IN ["01b88f7f-4de6-4daa-9562-a2c902e818ad"] and publishTimestamp between 1466445409000 and 1466531809000; 
{ 
    "requestID": "61afcf02-3b3d-4c8a-aec6-b76c4c1f7b17", 
    "signature": "json", 
    "results": [ 
     { 
      "#operator": "Sequence", 
      "~children": [ 
       { 
        "#operator": "IndexScan", 
        "index": "indexName", 
        "keyspace": "bucketName", 
        "namespace": "default", 
        "spans": [ 
         { 
          "Range": { 
           "High": [ 
            "successor(\"01b88f7f-4de6-4daa-9562-a2c902e818ad\")" 
           ], 
           "Inclusion": 1, 
           "Low": [ 
            "\"01b88f7f-4de6-4daa-9562-a2c902e818ad\"" 
           ] 
          } 
         } 
        ], 
        "using": "gsi" 
       }, 
       { 
        "#operator": "Parallel", 
        "~child": { 
         "#operator": "Sequence", 
         "~children": [ 
          { 
           "#operator": "Fetch", 
           "keyspace": "bucketName", 
           "namespace": "default" 
          }, 
          { 
           "#operator": "Filter", 
           "condition": "(((((`bucketName`.`ParentMsgId`) is not missing) and ((`bucketName`.`docType`) = \"msg\")) and ((`bucketName`.`ParentMsgId`) in [\"01b88f7f-4de6-4daa-9562-a2c902e818ad\"])) and ((`bucketName`.`publishTimestamp`) between 1466445409000 and 1466531809000))" 
          }, 
          { 
           "#operator": "InitialGroup", 
           "aggregates": [ 
            "count(*)" 
           ], 
           "group_keys": [] 
          } 
         ] 
        } 
       }, 
       { 
        "#operator": "IntermediateGroup", 
        "aggregates": [ 
         "count(*)" 
        ], 
        "group_keys": [] 
       }, 
       { 
        "#operator": "FinalGroup", 
        "aggregates": [ 
         "count(*)" 
        ], 
        "group_keys": [] 
       }, 
       { 
        "#operator": "Parallel", 
        "~child": { 
         "#operator": "Sequence", 
         "~children": [ 
          { 
           "#operator": "InitialProject", 
           "result_terms": [ 
            { 
             "as": "msgCount", 
             "expr": "count(*)" 
            } 
           ] 
          }, 
          { 
           "#operator": "FinalProject" 
          } 
         ] 
        } 
       } 
      ] 
     } 
    ], 
    "status": "success", 
    "metrics": { 
     "elapsedTime": "2.748194ms", 
     "executionTime": "2.660232ms", 
     "resultCount": 1, 
     "resultSize": 3274 
    } 
} 

Logs

java.lang.Thread.run(Thread.java:745) 
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) 
org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:293) 
org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:50) 
org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:218) 
org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:582) 
org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:919) 
org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441) 
org.eclipse.jetty.server.Server.handle(Server.java:349) 
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) 
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) 
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:875) 
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186) 
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:409) 
org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:117) 
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:941) 
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227) 
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:483) 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119) 
org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:70) 
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:480) 
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:547) 
org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:201) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:693) 
org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:150) 
org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:225) 
org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130) 
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:194) 
org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:214) 
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:237) 
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) 
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262) 
org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94) 
org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58) 
org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:89) 
org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:168) 
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) 
org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) 
java.lang.reflect.Method.invoke(Method.java:498) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
biz.te2.core.services.beacon.impl.BeaconResource.getVenuesBeaconData(BeaconResource.java:105) 
xxx.xxx.xxx.getBeaconHealthForRangeAndVenue(BeaconHealthServiceImpl.java:40) 
xxx.xxx.xxx..getAllMessagesCount(BeaconHealthServiceImpl.java:80) 
com.sun.proxy.$Proxy146.getMessageCountForDuration(Unknown Source) 
org.apache.aries.proxy.impl.ProxyHandler.invoke(ProxyHandler.java:78) 
org.apache.aries.proxy.impl.DefaultWrapper.invoke(DefaultWrapper.java:31) 
org.apache.aries.proxy.impl.ProxyHandler$1.invoke(ProxyHandler.java:50) 
java.lang.reflect.Method.invoke(Method.java:498) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
xxx.xxx.xxx.getMessageCountForDuration(MessageCouchbaseRepo.java:364) 
xxx.xxx.xxx.getN1qlQueryRows(MessageCouchbaseRepo.java:372) 
com.couchbase.client.java.CouchbaseBucket.query(CouchbaseBucket.java:582) 
com.couchbase.client.java.CouchbaseBucket.query(CouchbaseBucket.java:656) 
com.couchbase.client.java.util.Blocking.blockForSingle(Blocking.java:74) 
java.util.concurrent.CountDownLatch.await(CountDownLatch.java:277) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1328) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1037) 
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) 

Dies ist ein Beispiel für eine Abfrage, die gut funktioniert, wie gewünscht.

public static final String EXPERIENCE_ID_STATEMENT = "Select id " + 
      "from read as exp " + 
      "where id is not missing " + 
      "and docType = 'experience' " + 
      "and venueId = $venueId " + 
      "and exp.rule.poiIds is not missing " + 
      "and any poi in exp.rule.poiIds satisfies poi = $poiId end"; 

Das einzige, was das Besondere an dieser Abfrage im Vergleich zu den anderen ist es eine IN-Klausel verwendet, und empfängt die Felder über eine parametrisierte JsonArray.

Es gibt keine Netzwerkverzögerungen. Ich denke nicht, dass dies ein Problem ist, da andere Abfragen funktionieren und sie im Wesentlichen hintereinander angekettet sind (ich habe auch getestet, diese Abfrage alleine auszuführen, und sie arbeitet immer noch extrem langsam).

App und CB sind beide auf AWS. Ich habe sowohl mit demselben AWS-Server als auch auf verschiedenen Servern getestet, in beiden Fällen gibt es Probleme. Ich habe einen Kunden bei AWS und nicht bei AWS, beide haben das Problem. Durch einen Client meine ich einen Mechanismus, der meine App aufruft. Es wird immer noch eine Zeitüberschreitung angezeigt, wenn die Abfrage aufgerufen wird.

My Collectcouchbase Protokolle sind hier s3.amazonaws.com/cb-customers/TE2/

Antwort

1

Ich fand das Problem mit der Parametrierung der Werte in der IN-Klausel zu tun hat. Als ich die Parametrisierung aus der Abfrage entfernte, konnte ich so schnell wie CBQ laufen. Meine einzige Option war, die Parametrisierung zu beenden. Ich versuchte, den sekundären Index ein wenig zu verschieben, indem ich die an das Ende der Feldliste bewegte, das half mir nicht.

Das zugrunde liegende Problem diagnostiziert von couchbase rep.

das zugrunde liegende Problem ist, dass, wenn Sie die IN-Werte in einem Parameter setzen, kann der Optimierer nicht die Klausel nur ein Wert IN annehmen. Da experienceId den Index führt, können wir nur eine Gleichheit verwenden, um den Index abwärts zu bewegen und die Schlüssel zu zählen, die anwenden, weil wir überspringen und scannen müssten. Ich würde vorschlagen, erstellen Sie die Index als (docType, publishTimestamp, ParentMsgId), so können wir weiterhin den Index auf die Bedingungen auf docType, publishTimestamp scannen, und wenden Sie den Filter auf experienceId später in der Pipeline .

0

Können Sie überprüfen/post die Ausgabe von EXPLAIN für diese Abfrage. Überprüfen Sie außerdem die Abfrage-/Indexprotokolle auf dem Server (und keine Netzwerkverzögerungen).

meine App von AWS laufen bekomme ich einen Timeout es nur diese Abfrage ist , die andere ist eine Zeitüberschreitung nicht.

Sind beide Client/app und CB/Server in AWS ??

Und post die andere Abfrage, die in diesem Setup funktioniert. Was ist einzigartig an dieser Abfrage, die nicht funktioniert?

-Prasad

+0

siehe meine aktualisierte Antwort –

+0

lassen Sie mich wissen, wenn Sie weitere Fragen haben –