Execute várias tarefas do BigQuery em paralelo

O BigQuery aloja vários conjuntos de dados públicos que estão disponíveis para consulta pelo público em geral. Neste tutorial, vai criar um fluxo de trabalho que executa várias tarefas de consulta do BigQuery em paralelo, o que demonstra uma melhoria no desempenho em comparação com a execução das tarefas em série, uma após a outra.

Execute uma tarefa de consulta do BigQuery

No BigQuery, pode executar uma tarefa de consulta interativa (a pedido). Para mais informações, consulte o artigo Executar tarefas de consulta interativas e em lote.

Consola

  1. Na Google Cloud consola, aceda à página BigQuery.

    Aceda ao BigQuery

  2. Introduza a seguinte consulta SQL do BigQuery na área de texto do editor de consultas:

    SELECT TITLE, SUM(views)
    FROM `bigquery-samples.wikipedia_pageviews.201207h`
    GROUP BY TITLE
    ORDER BY SUM(views) DESC
    LIMIT 100
    
  3. Clique em Executar.

bq

No terminal, introduza o seguinte comando bq query para executar uma consulta interativa com a sintaxe SQL padrão:

bq query \
--use_legacy_sql=false \
'SELECT
  TITLE, SUM(views)
FROM
  `bigquery-samples.wikipedia_pageviews.201207h`
GROUP BY
  TITLE
ORDER BY
  SUM(views) DESC
LIMIT 100'

Isto executa uma consulta que devolve os 100 principais títulos da Wikipédia com mais visualizações num mês específico e escreve o resultado numa tabela temporária.

Tenha em atenção o tempo que a consulta demora a ser executada.

Implemente um fluxo de trabalho que execute várias consultas em série

Uma definição de fluxo de trabalho é composta por uma série de passos descritos através da sintaxe dos fluxos de trabalho. Depois de criar um fluxo de trabalho, implementa-o para o disponibilizar para execução. O passo de implementação também valida se é possível executar o ficheiro de origem.

O fluxo de trabalho seguinte define uma lista de cinco tabelas para executar uma consulta em relação às mesmas usando o conetor do BigQuery. As consultas são executadas em série, uma após a outra, e os títulos mais vistos de cada tabela são guardados num mapa de resultados.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Clique em Criar.

  3. Introduza um nome para o novo fluxo de trabalho, como workflow-serial-bqjobs.

  4. Escolha uma região adequada; por exemplo, us-central1.

  5. Selecione a conta de serviço que criou anteriormente.

    Já deve ter concedido as funções de IAM BigQuery > Utilizador da tarefa do BigQuery e Logging > Escritor de registos à conta de serviço.

  6. Clicar em Seguinte.

  7. No editor de fluxos de trabalho, introduza a seguinte definição para o seu fluxo de trabalho:

    main:
        steps:
        - init:
            assign:
                - results : {} # result from each iteration keyed by table name
                - tables:
                    - 201201h
                    - 201202h
                    - 201203h
                    - 201204h
                    - 201205h
        - runQueries:
            for:
                value: table
                in: ${tables}
                steps:
                - logTable:
                    call: sys.log
                    args:
                        text: ${"Running query for table " + table}
                - runQuery:
                    call: googleapis.bigquery.v2.jobs.query
                    args:
                        projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                        body:
                            useLegacySql: false
                            useQueryCache: false
                            timeoutMs: 30000
                            # Find top 100 titles with most views on Wikipedia
                            query: ${
                                "SELECT TITLE, SUM(views)
                                FROM `bigquery-samples.wikipedia_pageviews." + table + "`
                                WHERE LENGTH(TITLE) > 10
                                GROUP BY TITLE
                                ORDER BY SUM(VIEWS) DESC
                                LIMIT 100"
                                }
                    result: queryResult
                - returnResult:
                    assign:
                        # Return the top title from each table
                        - results[table]: {}
                        - results[table].title: ${queryResult.rows[0].f[0].v}
                        - results[table].views: ${queryResult.rows[0].f[1].v}
        - returnResults:
            return: ${results}
  8. Clique em Implementar.

gcloud

  1. Abra um terminal e crie um ficheiro de código-fonte para o seu fluxo de trabalho:

    touch workflow-serial-bqjobs.yaml
  2. Copie o seguinte fluxo de trabalho para o ficheiro de código-fonte:

    main:
        steps:
        - init:
            assign:
                - results : {} # result from each iteration keyed by table name
                - tables:
                    - 201201h
                    - 201202h
                    - 201203h
                    - 201204h
                    - 201205h
        - runQueries:
            for:
                value: table
                in: ${tables}
                steps:
                - logTable:
                    call: sys.log
                    args:
                        text: ${"Running query for table " + table}
                - runQuery:
                    call: googleapis.bigquery.v2.jobs.query
                    args:
                        projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                        body:
                            useLegacySql: false
                            useQueryCache: false
                            timeoutMs: 30000
                            # Find top 100 titles with most views on Wikipedia
                            query: ${
                                "SELECT TITLE, SUM(views)
                                FROM `bigquery-samples.wikipedia_pageviews." + table + "`
                                WHERE LENGTH(TITLE) > 10
                                GROUP BY TITLE
                                ORDER BY SUM(VIEWS) DESC
                                LIMIT 100"
                                }
                    result: queryResult
                - returnResult:
                    assign:
                        # Return the top title from each table
                        - results[table]: {}
                        - results[table].title: ${queryResult.rows[0].f[0].v}
                        - results[table].views: ${queryResult.rows[0].f[1].v}
        - returnResults:
            return: ${results}
  3. Implemente o fluxo de trabalho introduzindo o seguinte comando:

    gcloud workflows deploy workflow-serial-bqjobs \
       --source=workflow-serial-bqjobs.yaml \
       --service-account=MY_SERVICE_ACCOUNT@MY_PROJECT.iam.gserviceaccount.com

    Substitua MY_SERVICE_ACCOUNT@MY_PROJECT.iam.gserviceaccount.com pelo email da conta de serviço que criou anteriormente.

    Já deve ter concedido as funções de IAM roles/bigquery.jobUser e roles/logging.logWriter à conta de serviço.

Execute o fluxo de trabalho e execute várias consultas em série

A execução de um fluxo de trabalho executa a definição do fluxo de trabalho atual associada ao fluxo de trabalho.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Na página Fluxos de trabalho, selecione o fluxo de trabalho workflow-serial-bqjobs para aceder à respetiva página de detalhes.

  3. Na página Detalhes do fluxo de trabalho, clique em Executar.

  4. Clique novamente em Executar.

  5. Veja os resultados do fluxo de trabalho no painel Saída.

gcloud

  1. Abra um terminal.

  2. Execute o fluxo de trabalho:

     gcloud workflows run workflow-serial-bqjob

A execução do fluxo de trabalho deve demorar aproximadamente um minuto ou cinco vezes o tempo de execução anterior. O resultado inclui cada tabela e tem um aspeto semelhante ao seguinte:

{
  "201201h": {
    "title": "Special:Search",
    "views": "14591339"
  },
  "201202h": {
    "title": "Special:Search",
    "views": "132765420"
  },
  "201203h": {
    "title": "Special:Search",
    "views": "123316818"
  },
  "201204h": {
    "title": "Special:Search",
    "views": "116830614"
  },
  "201205h": {
    "title": "Special:Search",
    "views": "131357063"
  }
}

Implemente e execute um fluxo de trabalho que executa várias consultas em paralelo

Em vez de executar cinco consultas sequencialmente, pode executá-las em paralelo fazendo algumas alterações:

 - runQueries:
    parallel:
        shared: [results]
        for:
            value: table
            in: ${tables}
  • Um passo parallel permite que cada iteração do ciclo for seja executada em paralelo.
  • A variável results é declarada como shared, o que permite que seja gravável por um ramo, e o resultado de cada ramo pode ser anexado à mesma.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Clique em Criar.

  3. Introduza um nome para o novo fluxo de trabalho, como workflow-parallel-bqjobs.

  4. Escolha uma região adequada; por exemplo, us-central1.

  5. Selecione a conta de serviço que criou anteriormente.

  6. Clicar em Seguinte.

  7. No editor de fluxos de trabalho, introduza a seguinte definição para o seu fluxo de trabalho:

    main:
        steps:
        - init:
            assign:
                - results : {} # result from each iteration keyed by table name
                - tables:
                    - 201201h
                    - 201202h
                    - 201203h
                    - 201204h
                    - 201205h
        - runQueries:
            parallel:
                shared: [results]
                for:
                    value: table
                    in: ${tables}
                    steps:
                    - logTable:
                        call: sys.log
                        args:
                            text: ${"Running query for table " + table}
                    - runQuery:
                        call: googleapis.bigquery.v2.jobs.query
                        args:
                            projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                            body:
                                useLegacySql: false
                                useQueryCache: false
                                timeoutMs: 30000
                                # Find top 100 titles with most views on Wikipedia
                                query: ${
                                    "SELECT TITLE, SUM(views)
                                    FROM `bigquery-samples.wikipedia_pageviews." + table + "`
                                    WHERE LENGTH(TITLE) > 10
                                    GROUP BY TITLE
                                    ORDER BY SUM(VIEWS) DESC
                                    LIMIT 100"
                                    }
                        result: queryResult
                    - returnResult:
                        assign:
                            # Return the top title from each table
                            - results[table]: {}
                            - results[table].title: ${queryResult.rows[0].f[0].v}
                            - results[table].views: ${queryResult.rows[0].f[1].v}
        - returnResults:
            return: ${results}
  8. Clique em Implementar.

  9. Na página Detalhes do fluxo de trabalho, clique em Executar.

  10. Clique novamente em Executar.

  11. Veja os resultados do fluxo de trabalho no painel Saída.

gcloud

  1. Abra um terminal e crie um ficheiro de código-fonte para o seu fluxo de trabalho:

    touch workflow-parallel-bqjobs.yaml
  2. Copie o seguinte fluxo de trabalho para o ficheiro de código-fonte:

    main:
        steps:
        - init:
            assign:
                - results : {} # result from each iteration keyed by table name
                - tables:
                    - 201201h
                    - 201202h
                    - 201203h
                    - 201204h
                    - 201205h
        - runQueries:
            parallel:
                shared: [results]
                for:
                    value: table
                    in: ${tables}
                    steps:
                    - logTable:
                        call: sys.log
                        args:
                            text: ${"Running query for table " + table}
                    - runQuery:
                        call: googleapis.bigquery.v2.jobs.query
                        args:
                            projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                            body:
                                useLegacySql: false
                                useQueryCache: false
                                timeoutMs: 30000
                                # Find top 100 titles with most views on Wikipedia
                                query: ${
                                    "SELECT TITLE, SUM(views)
                                    FROM `bigquery-samples.wikipedia_pageviews." + table + "`
                                    WHERE LENGTH(TITLE) > 10
                                    GROUP BY TITLE
                                    ORDER BY SUM(VIEWS) DESC
                                    LIMIT 100"
                                    }
                        result: queryResult
                    - returnResult:
                        assign:
                            # Return the top title from each table
                            - results[table]: {}
                            - results[table].title: ${queryResult.rows[0].f[0].v}
                            - results[table].views: ${queryResult.rows[0].f[1].v}
        - returnResults:
            return: ${results}
  3. Implemente o fluxo de trabalho introduzindo o seguinte comando:

    gcloud workflows deploy workflow-parallell-bqjobs \
       --source=workflow-parallel-bqjobs.yaml \
       --service-account=MY_SERVICE_ACCOUNT@MY_PROJECT.iam.gserviceaccount.com

    Substitua MY_SERVICE_ACCOUNT@MY_PROJECT.iam.gserviceaccount.com pelo email da conta de serviço que criou anteriormente.

  4. Execute o fluxo de trabalho:

     gcloud workflows run workflow-parallel-bqjobs

O resultado é semelhante ao resultado anterior, mas a execução do fluxo de trabalho deve demorar aproximadamente 20 segundos ou menos!