大查询插入的上传时间比预期的长

时间:2014-03-25 20:38:30

标签: google-bigquery

我将数据作为带有JSON模式的csv格式上传到大查询。我所看到的是加载大查询的时间很长。当负载为DONE时,我从pollJob.getStatistics()获取开始和结束加载时间,并将增量时间计算为(startTime - endTime)/ 1000。然后我看一下加载的字节数。数据来自存储在谷歌云存储中的文件,我在应用引擎中重新处理以进行一些重新格式化。我将字符串转换为字节流,然后加载为负载的内容,如下所示:

public static void uploadFileToBigQuerry(TableSchema tableSchema,String tableData,String datasetId,String tableId,boolean formatIsJson,int waitSeconds,String[] fileIdElements)  {

    /* Init diagnostic */
    String projectId = getProjectId();

    if (ReadAndroidRawFile.testMode)  {
        String s = String.format("My project ID at start of upload to BQ:%s datasetID:%s tableID:%s json:%b \nschema:%s tableData:\n%s\n",
            projectId,datasetId,tableId,formatIsJson,tableSchema.toString(),tableData);
        log.info(s);
    }
    else  {
        String s = String.format("Upload to BQ tableID:%s tableFirst60Char:%s\n",
                tableId,tableData.substring(0,60));
        log.info(s);
    }

    /* Setup the data each time */
    Dataset dataset = new Dataset();
    DatasetReference datasetRef = new DatasetReference();
    datasetRef.setProjectId(projectId);
    datasetRef.setDatasetId(datasetId);
    dataset.setDatasetReference(datasetRef);

    try {
        bigquery.datasets().insert(projectId, dataset).execute();
    } catch (IOException e) {
        if (ReadAndroidRawFile.testMode) {
            String se = String.format("Exception creating datasetId:%s",e);
            log.info(se);
        }
    }


    /* Set destination table */
    TableReference destinationTable = new TableReference();
    destinationTable.setProjectId(projectId);
    destinationTable.setDatasetId(datasetId);
    destinationTable.setTableId(tableId);

    /* Common setup line */
    JobConfigurationLoad jobLoad = new JobConfigurationLoad();

    /* Handle input format */
    if (formatIsJson)  {
        jobLoad.setSchema(tableSchema);
        jobLoad.setSourceFormat("NEWLINE_DELIMITED_JSON"); 
        jobLoad.setDestinationTable(destinationTable);
        jobLoad.setCreateDisposition("CREATE_IF_NEEDED");
        jobLoad.setWriteDisposition("WRITE_APPEND");
        jobLoad.set("Content-Type", "application/octet-stream");
    }
    else  {
        jobLoad.setSchema(tableSchema); 
        jobLoad.setSourceFormat("CSV"); 
        jobLoad.setDestinationTable(destinationTable);
        jobLoad.setCreateDisposition("CREATE_IF_NEEDED");
        jobLoad.setWriteDisposition("WRITE_APPEND");
        jobLoad.set("Content-Type", "application/octet-stream");
    }

    /* Setup the job config */
    JobConfiguration jobConfig = new JobConfiguration();
    jobConfig.setLoad(jobLoad);
    JobReference jobRef = new JobReference();
    jobRef.setProjectId(projectId);

    Job outputJob = new Job();
    outputJob.setConfiguration(jobConfig);
    outputJob.setJobReference(jobRef);

    /* Convert input string into byte stream */
    ByteArrayContent contents = new ByteArrayContent("application/octet-stream",tableData.getBytes());  

    int timesToSleep = 0;
    try {
        Job job = bigquery.jobs().insert(projectId,outputJob,contents).execute();
        if (job == null)  {
            log.info("Job is null...");
            throw new Exception("Job is null");
        }

        String jobIdNew = job.getId();
        //log.info("Job is NOT null...id:");
        //s = String.format("job ID:%s jobRefId:%s",jobIdNew,job.getJobReference());
        //log.info(s);

        while (true) {
            try{
                Job pollJob = bigquery.jobs().get(jobRef.getProjectId(), job.getJobReference().getJobId()).execute();
                String status = pollJob.getStatus().getState();
                String errors = "";
                String workingDataString = "";

                if ((timesToSleep % 10) == 0)  {
                    String statusString = String.format("Job status (%dsec) JobId:%s status:%s\n", timesToSleep, job.getJobReference().getJobId(), status);
                    log.info(statusString);
                }

                if (pollJob.getStatus().getState().equals("DONE")) {
                    status = String.format("Job done, processed %s bytes\n", pollJob.getStatistics().toString()); //  getTotalBytesProcessed());
                    log.info(status);  // compute load stats with this string
                    if ((pollJob.getStatus().getErrors() != null)) {
                        errors = pollJob.getStatus().getErrors().  toString();
                        log.info(errors);
                    }

我得到的表现如下:BYTES /(deltaTime)的中值上传是17 BYTES /秒!是的,字节,而不是千克或大...

更糟糕的是,有时只有几百个字节,只有一行,最多需要5分钟。我通常没有错误,但我认为有了这个性能,我将无法在更多数据到达之前上传每个应用程序。我正在使用后端实例中的任务队列进行处理。经过大约一个小时的处理后,此任务队列会超时。

由于内容方法,这是否表现不佳?

1 个答案:

答案 0 :(得分:1)

有几件事:

  • 如果要加载少量数据,最好使用TableData.insertAll()而不是加载作业,这样可以发布数据并立即使用。

  • 加载作业是面向批处理的作业。也就是说,您可以根据需要插入(或多或少)多个,并在有资源时进行处理。有时您创建一个作业,而工作池正在调整大小,因此您必须等待。有时工人池已满。

  • 如果您提供项目&我们可以通过工作ID了解各个工作的表现,看看这些工作花了这么长时间。

  • 并行加载作业流程;也就是说,一旦他们开始执行,他们应该很快,但是开始执行的时间可能需要很长时间。

  • 作业统计信息中有三个时间字段。 createTime,startTime和endTime。

    • createTime是BigQuery服务器收到您的请求的时刻。
    • startTime是BigQuery实际开始工作的时候
    • endTime是作业完成的时间

    我希望大部分时间都花在创建和开始之间。如果小型工作不是这种情况,那么这意味着某些事情很奇怪,而且工作ID可以帮助诊断问题。