2016-08-09 30 views
8

Używając serwera Couchbase 4.1.0 (i 4.5), Java SDK 2.2.8 (wypróbowany również przy użyciu wersji 2.2.7, 2.3.1, & 2.3.3), mam zapytanie wykorzystanie indeksu wtórnego, który działa poprawnie, gdy uruchamiam mój kod lokalnie, a nawet za pośrednictwem CBQ (CBQ trwa około 3ms) na serwerze AWS. Jednak po uruchomieniu aplikacji na AWS otrzymuję TimeOutException i jest to tylko jedno zapytanie, które kończy się z czasem, a inne nie. Szczegóły poniżej.Kwerendy N1QL przekroczą limit czasu, gdy użyjesz parametru IN z parametryzowaną klauzulą ​​IN

Warto zauważyć, że moja konfiguracja Couchbase ma 3 wiadra.

Przykład 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" 
} 

Wskaźnik wtórne:

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

Przykład zapytań pochodzących z N1qlQuery#n1ql()

{"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"] 
} 

kod Java

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); 
    ... 
} 

Zapytanie Wyjaśnić Wynik

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 
    } 
} 

Dzienniki

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) 

To jest przykład kwerendy, która działa prawidłowo, zgodnie z wnioskiem.

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"; 

Jedyne co wyróżnia tego zapytania w porównaniu z innymi, jest to korzysta z klauzuli IN i otrzymuje pola poprzez parametryzowanego JsonArray.

Brak opóźnień sieciowych. Nie sądzę, że to jest problem, ponieważ inne zapytania działają i są one w istocie powiązane zwane jeden po drugim (testowałem również uruchamianie tego samego zapytania i nadal działa bardzo wolno).

Aplikacja i CB są w AWS. Przetestowałem zarówno na tym samym serwerze AWS, jak i na różnych serwerach, w obu przypadkach jest problem. Mam klienta na AWS, a nie na AWS, oba mają problem. Przez klienta mam na myśli mechanizm, który wywołuje moją aplikację. Nadal dostaje limit czasu, gdy wywoływane jest zapytanie.

Moje dzienniki collectinfo couchbase tutaj s3.amazonaws.com/cb-customers/TE2/

Odpowiedz

1

znalazłem problem, że ma do czynienia z parametryzacją wartości w klauzula. Po usunięciu parametryzacji z zapytania mogłem uruchomić tak szybko, jak CBQ. Moją jedyną opcją było upuszczenie parametryzacji. Próba dostosowania indeksu wtórnego, nieco przesunięcia ParentMsgId na końcu listy pól, nie pomogła w moim przypadku.

Podstawowy problem zdiagnozowany z republikańskiej rep.

podstawowa kwestia jest to, że raz można umieścić wartości w w parametrze , Optymalizator nie można zakładać, klauzula ma tylko jeden wartość. Ponieważ parametr experienceId prowadzi indeks, możemy użyć tylko równości , aby przejść do indeksu i rozpocząć odliczanie kluczy, które mają zastosowanie , ponieważ musielibyśmy pominąć i zeskanować. Sugerowałbym utworzenie indeksu jako (docType, publishingTimestamp, ParentMsgId), w ten sposób możemy nadal skanować indeks na warunkach określonych na docType, publishTimestamp, i zastosować filtr na experienceId później w rurociągu .

0

można sprawdzić/zakładać wyjście EXPLAIN dla tego zapytania. Sprawdź również dzienniki zapytania/indeksu na serwerze (bez opóźnień sieciowych).

uruchomiony mojej aplikacji z AWS dostaję TimeOutException Dopiero ta kwerenda którym jest czas na inne nie.

Są zarówno klient/app i CB/serwer w AWS ??

I, dodaj inne zapytanie, które działa w tej konfiguracji. Co jest wyjątkowego w tym zapytaniu, które nie działa?

-Prasad

+0

zobacz moją zaktualizowaną odpowiedź –

+0

daj mi znać, jeśli masz dodatkowe pytania –