BigQuery Ottenere "risposta troppo grande" quando si utilizza la funzione Ntile con il set di dati di esempio pubblico su Wikipedia

StackOverflow https://stackoverflow.com//questions/22055788

  •  21-12-2019
  •  | 
  •  

Domanda

Fondamentalmente sto testando la funzione Ntile per dividere il conteggio totale della parola della tabella di Wikipedia in 100 secchi.Sto ricevendo la "risposta troppo grande errore" utilizzando la console web.Così ho provato lo strumento BQ CLI con entrambe le opzioni --Destination_table e --allow_large_results senza fortuna.

Ecco la query:

SELECT id, num_characters, NTILE(100) OVER (ORDER BY num_characters) percentile
FROM [publicdata:samples.wikipedia]
.

Come posso recuperare correttamente i risultati?

È stato utile?

Soluzione

Segreto di BigQuery per prestazioni sorprendenti: distribuzione del carico di lavoro. Ogni volta che si rilascia una query, un grande numero di computer inizia a leggere tutti i dati in parallelo, elaborandolo e passandolo ad altri computer nella catena.

Tuttavia, ci sono operazioni molto difficili da parallelizzare - tipicamente funzioni che corrono dopo che tutto il resto è stato fatto. Quelle operazioni non vengono distribuite, ma vincolate a tutti i dati che si adattano a un computer. Ordina per e oltre () sono alcune di queste funzioni - come alla fine una singola macchina deve ordinare l'intero risultato impostato.

La buona notizia è che abbiamo alternative. Quantili è in grado di passare attraverso tutti i dati, mentre il calcolo dei risultati approssimativi:

SELECT QUANTILES(num_characters, 100)
FROM [publicdata:samples.wikipedia]

Query complete (1.7s elapsed, 2.34 GB processed)
.

o eseguire lo stesso sopra (ordine per) rispetto alla domanda originale, ma su un campione dei dati:

SELECT id, num_characters, NTILE(100) OVER (ORDER BY num_characters) percentile 
FROM [publicdata:samples.wikipedia]
WHERE id % 10 = 0;

Query complete (258.7s elapsed, 4.68 GB processed)
.

Vedrai che entrambi producono risultati simili (uno per approssimazione, l'altro per campionamento) - ma uno è molto più veloce.

Altri suggerimenti

È possibile utilizzare una funzione UDF per ottenere ntili di tutti i dati senza saturazione della memoria e senza dover campionare, anche se potrebbe essere meno performante.

Ho impiegato questo metodo per calcolare il percentile un valore caduto all'interno, proprio come la funzione generatagODicetagCode integrata.La funzione incorporata esaurirebbe la memoria durante l'operazione NTILE, se applicata a un numero massiccio di righe.

La funzione definita dall'utente prende un array Quantili (in questo caso generato utilizzando ORDER BY) e un valore e restituisce quale ntile il valore è in.

-- Define UDF
CREATE TEMPORARY FUNCTION getNTile(quantiles ARRAY<INT64>, val INT64)
  RETURNS INT64
  LANGUAGE js AS """
    var ntile = 0;

    while(parseInt(val, 10) > parseInt(quantiles[ntile], 10) && ntile < quantiles.length) {
      ntile+=1;
    }

    return ntile;
  """;

-- Calculate an array of approximate quantiles, in this case percentiles
WITH master AS (
  SELECT
    id,
    num_characters
  FROM
    `publicdata.samples.wikipedia`
),
quantiles AS (
  SELECT
    APPROX_QUANTILES(num_characters, 99) AS approx
  FROM
    master
)

-- Use UDF with approx quantile array to find nTile
SELECT
  id,
  num_characters,
  getNTile(quantiles.approx, num_characters) AS percentile
FROM
  master,
  quantiles
.

Il codice JS nell'UDF sta costringendo i valori agli interi con APPROX_QUANTILES.Potrebbe essere un bug bigquery, ma per qualche motivo i valori stavano arrivando come stringhe altrimenti, stranamente.

Spero che questo aiuti qualcuno.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top