2016-04-04 4 views
0

Diese Frage ist wahrscheinlich eine andere InstanzBigQuery Javascript UDF nicht mit „Ressourcen überschritten“

BigQuery UDF memory exceeded error on multiple rows but works fine on single row

Aber es wurde vorgeschlagen, dass ich als Frage posten statt einer Antwort.

Ich benutze Javascript, um Logfiles in eine Tabelle zu analysieren. Die JavaScript Pars-Funktion ist relativ einfach. Es funktioniert bei 1M Zeilen, scheitert aber bei 3M Zeilen. Log-Dateien können viel größer sein als die 3M, so dass ein Fehler auftritt.

Die Funktion ist unten.

function parseLogRow(row, emit) { 

    r = (row.logrow ? row.logrow : "") + (row.l2 ? " " + row.l2 : "") + (row.l3 ? " " + row.l3 : "") 
    ts = null 
    category = null 
    user = null 
    message = null 
    db = null 
    seconds = null 
    found = false 
    if (r) { 
     m = r.match(/^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (\+|\-)\d\d\d\d) \[([^|]*)\|([^|]*)\|([^\]]*)\] ::(\(([\d\.]+)s\))? (.*)/) 
     if(m){ 
      ts = new Date(m[1])*1 
      category = m[3] || null 
      user = m[4] || null 
      db = m[5] || null 
      seconds = m[7] || null 
      message = m[8] || null 
      found = true 
     } 
     else { 
      message = r 
      found = false 
     } 
    } 

    emit({ 
     ts: ts, 
     category: category, 
     user: user, 
     db: db, 
     seconds: seconds*1.0, 
     message: message, 
     found: found 
     }); 
    } 


    bigquery.defineFunction(
    'parseLogRow',       // Name of the function exported to SQL 
    ['logrow',"l2","l3"],     // Names of input columns 
    [ 
     {'name': 'ts', 'type': 'float'}, // Output schema 
     {'name': 'category', 'type': 'string'}, 
     {'name': 'user', 'type': 'string'}, 
     {'name': 'db', 'type': 'string'}, 
     {'name': 'seconds', 'type': 'float'}, 
     {'name': 'message', 'type': 'string'}, 
     {'name': 'found', 'type': 'boolean'}, 
    ], 
    parseLogRow       // Reference to JavaScript UDF 
); 

Ich Verweis auf die Funktion mit dieser Abfrage:

SELECT 
    ROW_NUMBER() OVER() as row_num, 
    ts,category,user, 
    db,seconds,message,found, 
FROM parseLogRow((SELECT * FROM[#{dataset}.today] 
     LIMIT 1000000 
    )) 

einige Beispieldaten in der 'heute' Tabelle sieht wie folgt aus (als CSV):

logrow,l2,l3 
# Logfile created on 2015-12-29 00:00:09 -0800 by logger.rb/v1.2.7,, 
2015-12-29 00:00:09.262 -0800 [INFO|7aaa0|] :: Running scheduled job: confirm running gulp process,, 
2015-12-29 00:00:09.277 -0800 [DEBUG|7aaa0|] :: Restarted gulp process,, 
2015-12-29 00:00:09.278 -0800 [INFO|7aaa0|] :: Completed scheduled job: confirm running gulp process,, 
2015-12-29 00:00:14.343 -0800 [DEBUG|7aaa2|scheduler] :: Polling for pending tasks (master: true),, 
2015-12-29 00:00:19.396 -0800 [INFO|7aaa4|] :: Running scheduled job: confirm running gulp process,, 
2015-12-29 00:00:19.409 -0800 [DEBUG|7aaa4|] :: Restarted gulp process,, 
2015-12-29 00:00:19.410 -0800 [INFO|7aaa4|] :: Completed scheduled job: confirm running gulp process,, 
2015-12-29 00:00:29.487 -0800 [INFO|7aaa6|] :: Running scheduled job: confirm running gulp process,, 
2015-12-29 00:00:29.500 -0800 [DEBUG|7aaa6|] :: Restarted gulp process,, 
2015-12-29 00:00:29.500 -0800 [INFO|7aaa6|] :: Completed scheduled job: confirm running gulp process,, 
2015-12-29 00:00:39.597 -0800 [INFO|7aaa8|] :: Running scheduled job: confirm running gulp process,, 
2015-12-29 00:00:39.610 -0800 [DEBUG|7aaa8|] :: Restarted gulp process,, 
2015-12-29 00:00:39.611 -0800 [INFO|7aaa8|] :: Completed scheduled job: confirm running gulp process,, 
2015-12-29 00:00:44.659 -0800 [DEBUG|7aaaa|scheduler] :: Polling for pending tasks (master: true),, 
2015-12-29 00:00:49.687 -0800 [INFO|7aaac|] :: Running scheduled job: confirm running gulp process,, 
2015-12-29 00:00:49.689 -0800 [DEBUG|7aaac|] :: Restarted gulp process,, 
2015-12-29 00:00:49.689 -0800 [INFO|7aaac|] :: Completed scheduled job: confirm running gulp process,, 
2015-12-29 00:00:59.869 -0800 [INFO|7aaae|] :: Running scheduled job: confirm running gulp process,, 
2015-12-29 00:00:59.871 -0800 [DEBUG|7aaae|] :: Restarted gulp process,, 

Diese ist ein bisschen ein Hack, wie ich das Protokoll als 3 Spalte Tabelle (wirklich, nur eine Spalte) importieren, indem Sie es als eine CSV mit dem Trennzeichen auf Registerkarte importieren (wir haben in der Regel keine Registerkarten in der Protokolldatei), die eine Abfrage verwenden, um es in die Tabelle zu verwandeln, die ich achte Verbündeter wollen.

Ich mag dieses Muster, weil es die Analyse schnell und verteilt ist (wenn es funktioniert).

Ein fehlgeschlagener Job ist: bigquery-gucker: bquijob_260be029_153dd96cfdb. Bitte kontaktieren Sie mich, wenn Sie einen reproduzierbaren Fall benötigen.

Jede Hilfe oder Anregung wäre willkommen.

Antwort

1

Point # 1
ich mit UDF siehe Ausgabe nicht - es funktioniert für mich sogar auf 10M Reihen
ich glaube, das Problem eher bei der Verwendung von ROW_NUMBER ist() OVER() - es entfernen und es sollte funktionieren!

SELECT 
    ts,category,user, 
    db,seconds,message,found, 
FROM parseLogRow((SELECT * FROM[#{dataset}.today] 
)) 

Point # 2
Von prospektiver Leistung sollte unter schneller laufen (glaube ich) und im Allgemeinen würde ich vorschlagen, vermeidet in Fällen mit UDF, wenn "plain" BQ auch

SELECT 
    REGEXP_EXTRACT(logrow, r'^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (?:\+|\-)\d\d\d\d) \[[^|]*\|[^|]*\|[^\]]*\] :: .*') AS ts, 
    REGEXP_EXTRACT(logrow, r'^(?:\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (?:\+|\-)\d\d\d\d) \[([^|]*)\|(?:[^|]*)\|(?:[^\]]*)\] :: (?:.*)') AS category, 
    REGEXP_EXTRACT(logrow, r'^(?:\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (?:\+|\-)\d\d\d\d) \[(?:[^|]*)\|([^|]*)\|(?:[^\]]*)\] :: (?:.*)') AS user, 
    REGEXP_EXTRACT(logrow, r'^(?:\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (?:\+|\-)\d\d\d\d) \[(?:[^|]*)\|(?:[^|]*)\|([^\]]*)\] :: (?:.*)') AS db, 
    REGEXP_EXTRACT(logrow, r'^(?:\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (?:\+|\-)\d\d\d\d) \[(?:[^|]*)\|(?:[^|]*)\|(?:[^\]]*)\] :: (.*)') AS message, 
    REGEXP_MATCH(logrow, r'^((?:\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d (?:\+|\-)\d\d\d\d) \[(?:[^|]*)\|(?:[^|]*)\|(?:[^\]]*)\] :: (?:.*))') AS found 
FROM (
    SELECT logrow +IFNULL(' ' + l2, '') + IFNULL(' ' + l3, '') AS logrow 
    FROM YourTable  
) 
+0

Dank funktioniert Du bist genau richtig. War das Javascript nicht die Fensterfunktion? Hier finden Sie weitere Informationen: http://stackoverflow.com/questions/33247703/rank-or-row-number-in-bigquery-over-a-large-dataset –