【问题标题】:BigQuery Java API not returning all rows when we execute query through it当我们通过 BigQuery Java API 执行查询时,它不会返回所有行
【发布时间】:2017-10-13 19:33:43
【问题描述】:

我们面临一个间歇性问题,当我们通过 BigQuery Java API 执行查询时,我们获得的行数与通过 BigQuery UI 执行相同查询时不匹配。

在我们的代码中,我们使用 QueryResponse 对象来执行查询,我们还通过检查标志来检查查询是否完成 GetQueryResultsResponse.getJobComplete(),如果查询没有在一个简短的时间内返回所有行,我们还具有提取更多记录的机制while(queryResult.getRows() != null && queryResult.getTotalRows().compareTo(BigInteger.valueOf((queryResult.getRows().size()))) > 0) {

以下是我们用于执行查询的代码:

int retryCount = 0;
    long waitTime = Constant.BASE_WAIT_TIME;
    Bigquery bigquery = cloudPlatformConnector.connectBQ();
    QueryRequest queryRequest = new QueryRequest();
    queryRequest.setUseLegacySql(useLegacyDialect);
    GetQueryResultsResponse queryResult = null;
    GetQueryResultsResponse queryPaginationResult = null;
    String pageToken;
    do{
         try{
               QueryResponse query = bigquery.jobs().query(this.projectId, queryRequest.setQuery(querySql)).execute();
               queryResult = bigquery.jobs().getQueryResults(query.getJobReference().getProjectId(), query.getJobReference().getJobId()).execute();                   
               if(queryResult != null ){
                  if(!queryResult.getJobComplete()){
                      LOGGER.info("JobId for the query : "+ query.getJobReference().getJobId() + " is Job Completed : "+ queryResult.getJobComplete());
                      if(queryResult.getErrors() != null){
                           for( ErrorProto err: queryResult.getErrors() ){
                               LOGGER.info("Errors in query, Reason : "+ err.getReason()+ " Location : "+ err.getLocation() +" Message : "+ err.getMessage());
                           }  
                      }
                       LOGGER.info("Query not completed : "+querySql);
                       throw new IOException("Query is failing retrying it");
                   }
               }
               LOGGER.info("JobId for the query : "+ query.getJobReference().getJobId() + " is Job Completed : "+ queryResult.getJobComplete() + " Total rows from query : " + queryResult.getTotalRows());
               pageToken = queryResult.getPageToken();
               while(queryResult.getRows() != null && queryResult.getTotalRows().compareTo(BigInteger.valueOf((queryResult.getRows().size()))) > 0) {
                   LOGGER.info("Inside the Pagination code block, Page Token : "+pageToken);
                   queryPaginationResult =  bigquery.jobs().getQueryResults(projectId,query.getJobReference().getJobId()).setPageToken(pageToken).setStartIndex(BigInteger.valueOf(queryResult.getRows().size())).execute();
                   queryResult.getRows().addAll(queryPaginationResult.getRows());
                   pageToken = queryPaginationResult.getPageToken();
                   LOGGER.info("Inside the Pagination code block, total size : "+ queryResult.getTotalRows() + " Current Size : "+ queryResult.getRows().size());
               }

         }catch(IOException ex){
               retryCount ++;
               LOGGER.info("BQ Connection Attempt "+retryCount +" failed, Retrying in " + waitTime + " seconds");
               if (retryCount == Constant.MAX_RETRY_LIMIT) {
                    LOGGER.info("BQ Connection Error", ex);
                    throw ex;
               }
               try {
                    Thread.sleep(waitTime);
               } catch (InterruptedException e) {
                    LOGGER.info("Thread Error");
               }
               waitTime *= 2;
         }
    }while((queryResult == null && retryCount < Constant.MAX_RETRY_LIMIT ) || (!queryResult.getJobComplete() && retryCount < Constant.MAX_RETRY_LIMIT));
    return queryResult.getRows();

我没有得到所有行的查询中没有任何限制子句。

目前我们使用的是 0.5.0 版本的 google-cloud-bigquery。

提前致谢!

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    我认为在后续调用getQueryResults 时,您需要正确调用setPageToken,并使用上一页返回的pageToken。否则getQueryResults 只会返回第一页中的行。

    【讨论】:

    • 谢谢,Nguyen,我试过这个东西,但没有成功,我面临同样的问题,看起来我的流程永远不会进入 while 块,在分页的情况下会拉出更多记录。我也更新了我上面的代码也考虑了pageToken。
    • 我看到您在 while 循环中添加了 .setPageToken(queryResult.getPageToken())。但是queryResult.getPageToken() 不总是第一页的页面标记吗?我认为您需要获取每个 getQueryResults 调用的查询令牌并将其放入下一个调用中。此外,您能否提供更多信息:(1)您期望的总行数是多少,(2)您的代码获取的行数,以及(3)它的信息日志输出是什么。
    • 我明白了你的意思,我可以更新我的代码,但我没有看到我在 while 循环中输入的任何日志语句,这迫使我认为这个问题与分页无关。 (1)如果我们谈论 10 月 14 日,我期望的总行数每天都会变化,那么我期望 3978 但只有 3972 差异并不总是那么接近,有时我也看到超过 500 行的差异跨度>
    • 根据你的数字,queryResult.getTotalRows() 应该返回 3978,queryResult.getRows().size() 应该返回 3972。3978 > 3972 所以它应该进入了 while 循环,对吧? (因为条件满足)。我的理解是正确的还是我遗漏了什么?
    • 请参阅我没有在代码中的任何位置记录 queryResult.getTotalRows() 当我通过 bigQuery UI 执行相同查询时获得的 3978 行但我的代码仅返回 3972 条记录,这就是为什么我我说我的代码流没有进入 while 循环,因为当我遇到这个问题时,我检查了日志,但没有看到 while 块中的任何日志语句。
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    相关资源
    最近更新 更多