Как я могу оптимизировать производительность при вставке массивных данных в набор данных BigQuery с помощью определенной пользователем функции - PullRequest
0 голосов
/ 09 апреля 2019

Я просто ищу способ добавить массивные данные в таблицу BigQuery с использованием UDF.Итак, я попробовал рекомендуемый метод следующим образом:

#standardSQL
INSERT INTO `project.dataset.Quincy` (id, col)
WITH array_to_loop_through AS (
  SELECT id 
  FROM UNNEST(GENERATE_ARRAY(1, 1000, 1)) id
)
SELECT id, CONCAT('Rank: ', CAST(id AS STRING))
FROM array_to_loop_through

Потребовалось 8 секунд, чтобы добавить 1 миллион значений в таблицу.Таким образом, я применил этот метод к своему UDF:

CREATE TEMPORARY FUNCTION myFunc()
  RETURNS array<string>
  LANGUAGE js AS
"""
a=[""];
for(i=0;i<=50;i++){
    a.push(randomString(12));
    }
    return a;
"""
OPTIONS (
library="gs://kaneki110299/tester.js"

);



#standardSQL

INSERT INTO `Lambert.fortune` (password)
WITH array_to_loop_through AS (
  SELECT * 
  FROM UNNEST(myFunc()) id
)
SELECT CONCAT(CAST(id AS STRING))
FROM array_to_loop_through

Когда я запускаю этот запрос в BigQuery, он выполняется в течение 5 минут, затем встречается тайм-аут UDF с 50 значениями.Та же ошибка произошла, когда я поместил цикл внутрь tester.js.Итак, я попробовал другой способ:

CREATE TEMPORARY FUNCTION myFunc()
  RETURNS string
  LANGUAGE js AS
"""   
    return randomString(12);
"""
OPTIONS (
library="gs://kaneki110299/tester.js"

);



#standardSQL

INSERT INTO `Lambert.fortune` (password) 
Values (myFunc()),(myFunc()),(myFunc())...//1000 times

В отличие от предыдущего запроса, этот запрос занимает всего 30 секунд, чтобы добавить 1000 значений из моего результата UDF в таблицу.Похоже, что цикл на BigQuery не работал хорошо или быстро.

Можно ли использовать параллельную поддержку или поддержку BigQuery любым способом для оптимизации производительности своего ЦП при запуске пользовательской функции для вставки массивных данных в его набор данных?Я попытался добавить 1 миллиард значений в таблицу, чтобы последний метод, который я использую, не казался практичным.

1 Ответ

0 голосов
/ 09 апреля 2019

Используя googleApi npm , вы можете написать программу JS, которая будет выполнять несколько вставок параллельно.

Это полный рабочий тест мокко о том, как использовать API для однократного вызова. Вы можете обернуть внутренний вызов своим собственным for loop, чтобы выполнить вставку параллельно.

if (!global._babelPolyfill) {
    var a = require("babel-polyfill")
}

import {google} from 'googleapis'

let bigQuery = google.bigquery("v2")

describe('Run query with API', async () => {

    it('Run a query', async () => {
        let result = await test('panada')

    })

    async function test(p1) {
        try {
            let query = `INSERT INTO \`project.dataset.Quincy\` (id, col)
                        WITH array_to_loop_through AS (
                          SELECT id 
                          FROM UNNEST(GENERATE_ARRAY(1, 10, 1)) id
                        )
                        SELECT id, CONCAT('Rank: ', CAST(id AS STRING))
                        FROM array_to_loop_through`

            let auth = getBasicAuthObj()
            auth.setCredentials({
                access_token: "myAccessToken",
                refresh_token: "myRefreshToken"
            })

            let request = {
                "projectId": "myProject",
                auth,
                "resource": {
                    "projectId": "myProject",
                    "configuration": {
                        "query": {
                            query,
                            "useLegacySql": false
                        },
                        "dryRun": false
                    }
                }
            }

            console.log(`query is: ${query}`)

            let result = await callBQ(request)

            // debugger
            console.log(`Status is: ${result.data.status.state}`)
        } catch (err) {
            console.log("err", err)
        }
    }

    /**
     * Call BigQuery jobs.insert
     * @param request
     * @returns {Promise<*>}
     */
    async function callBQ(request) {
        debugger
        // console.log("request", request)
        try {
            let result = await bigQuery.jobs.insert(request, request)
            console.log(`All good.....`)

            return result
        } catch (e) {
            console.log(`Failed to run query: ${e}`)
        }

    }

    /**
     * Create oAuth object
     * @returns {OAuth2Client}
     */
    function getBasicAuthObj() {
        let clientId = 'myclientId'
        let clientSecret = 'mySecret'
        let redirectUrl = 'URL'

        return new google.auth.OAuth2(
            clientId,
            clientSecret,
            redirectUrl
        )
    }
})

Примечание: Bigquery имеет ограничения при параллельной вставке и выполнении запросов. Для получения дополнительной информации см. Эту ссылку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...