Google BigQuery è il data warehouse serverless di Google, costruito per eseguire query analitiche su tabelle molto grandi. Quando vuoi estrarre i dati delle tabelle da BigQuery verso la tua applicazione, la via più veloce è la BigQuery Storage Read API, un servizio gRPC che trasmette le righe direttamente dallo storage invece di paginarle attraverso un endpoint REST. sgcWebSockets Enterprise include un client gRPC BigQuery tipizzato che poggia su TsgcGRPCClient, così puoi leggere una tabella BigQuery da Delphi e C++Builder senza alcun runtime gRPC esterno.
Come funziona
La Storage Read API è un servizio gRPC chiamato google.cloud.bigquery.storage.v1.BigQueryRead. gRPC è costituito da Protocol Buffers incapsulati su HTTP/2, quindi il client gira sullo stack HTTP/2 di sgcWebSockets. Punti un TsgcHTTP2Client a bigquerystorage.googleapis.com sulla porta 443 con TLS, lo assegni a un TsgcGRPCClient e il client gRPC si occupa per te dell'incapsulamento dei messaggi, degli header, dei timeout e dei trailer.
Leggere una tabella è uno schema a due chiamate. Prima chiami CreateReadSession, una chiamata unaria che chiede a BigQuery di aprire una sessione su una tabella e restituire uno o più read stream. Poi chiami ReadRows su uno stream, una chiamata server-streaming: invii una richiesta e il server spinge di ritorno una sequenza di batch di righe finché lo stream non termina. I messaggi BigQuery tipizzati in sgcGRPC_Google_BigQuery costruiscono i protobuf delle richieste e analizzano le risposte, così lavori con classi Delphi invece di byte assemblati a mano.
Autenticazione
BigQuery è autenticato con un account di servizio Google Cloud. La demo carica il JSON dell'account di servizio, costruisce un JWT autofirmato e lo scambia con un token di accesso, poi invia quel token come metadata gRPC su ogni chiamata. Poiché un JWT autofirmato dell'account di servizio è vincolato all'audience, il token deve puntare all'endpoint BigQuery Storage in modo che sia accettato da bigquerystorage.googleapis.com.
GoogleCloud.GoogleCloudOptions.Authentication := gcaJWT;
GoogleCloud.GoogleCloudOptions.JWT.ClientEmail := ClientEmail;
GoogleCloud.GoogleCloudOptions.JWT.PrivateKeyId := PrivateKeyId;
GoogleCloud.GoogleCloudOptions.JWT.PrivateKey.Text := PrivateKey;
GoogleCloud.GoogleCloudOptions.JWT.ProjectId := ProjectId;
GoogleCloud.GoogleCloudOptions.JWT.API_Endpoint :=
'https://bigquerystorage.googleapis.com/';
// once the token is acquired, attach it to every gRPC call
GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);
Configurare il client
Un canale gRPC è una connessione HTTP/2. Crea il trasporto, puntalo all'host BigQuery Storage, poi crea il client gRPC e assegna il trasporto alla sua proprietà Client. Il content type è il formato di filo proto binario e la compressione è lasciata disattivata.
uses
sgcHTTP2_Client, sgcGRPC_Client, sgcGRPC_Types, sgcGRPC_Google_BigQuery;
var
HTTP2: TsgcHTTP2Client;
GRPC: TsgcGRPCClient;
begin
HTTP2 := TsgcHTTP2Client.Create(nil);
HTTP2.Host := 'bigquerystorage.googleapis.com';
HTTP2.Port := 443;
HTTP2.TLS := True;
GRPC := TsgcGRPCClient.Create(nil);
GRPC.Client := HTTP2;
GRPC.ChannelOptions.ContentType := grpcProto;
GRPC.ChannelOptions.Compression := grpcNoCompression;
HTTP2.Active := True;
end;
Creare una read session
Per aprire una sessione compili un TsgcGRPCBigQueryCreateReadSessionRequest. Il Parent è il tuo progetto di fatturazione, ReadSession.Table è il percorso della tabella completamente qualificato e DataFormat seleziona il formato di filo delle righe (1 = Avro, 2 = Arrow). MaxStreamCount limita quanti read stream paralleli restituisce BigQuery. Serializza la richiesta con ToBytes e inviala come Call unaria; la risposta è una ReadSession che carichi con LoadFromBytes per leggere di ritorno i nomi degli stream.
var
oRequest: TsgcGRPCBigQueryCreateReadSessionRequest;
oResponse: TsgcGRPCResponse;
oSession: TsgcGRPCBigQueryReadSession;
begin
oRequest := TsgcGRPCBigQueryCreateReadSessionRequest.Create;
try
oRequest.Parent := 'projects/' + ProjectId;
oRequest.ReadSession.Table := 'projects/' + ProjectId +
'/datasets/' + Dataset + '/tables/' + Table;
oRequest.ReadSession.DataFormat := 1; { AVRO }
oRequest.MaxStreamCount := 1;
oResponse := GRPC.Call(
'google.cloud.bigquery.storage.v1.BigQueryRead',
'CreateReadSession', oRequest.ToBytes);
if oResponse.StatusCode = grpcOK then
begin
oSession := TsgcGRPCBigQueryReadSession.Create;
try
oSession.LoadFromBytes(oResponse.Data);
// keep the first read stream name for ReadRows
if oSession.StreamCount > 0 then
FReadStreamName := oSession.Stream(0).Name;
finally
oSession.Free;
end;
end;
finally
oRequest.Free;
end;
end;
Trasmettere le righe
Con un nome di stream in mano chiami ReadRows. Imposta ReadStream al nome dello stream e un Offset di partenza opzionale, poi invialo con CallAsync per una risposta server-streaming. Ogni batch che il server spinge solleva OnGRPCStreamMessage e OnGRPCStreamEnd scatta una volta quando lo stream è terminato.
var
oRequest: TsgcGRPCBigQueryReadRowsRequest;
begin
oRequest := TsgcGRPCBigQueryReadRowsRequest.Create;
try
oRequest.ReadStream := FReadStreamName;
oRequest.Offset := 0;
GRPC.CallAsync('google.cloud.bigquery.storage.v1.BigQueryRead',
'ReadRows', oRequest.ToBytes);
finally
oRequest.Free;
end;
end;
procedure TForm1.OnGRPCStreamMessage(Sender: TObject;
const aMessage: TsgcGRPCStreamMessage; var aCancel: Boolean);
var
oResponse: TsgcGRPCBigQueryReadRowsResponse;
begin
oResponse := TsgcGRPCBigQueryReadRowsResponse.Create;
try
oResponse.LoadFromBytes(aMessage.Data);
if oResponse.AvroRows.RowCount > 0 then
// oResponse.AvroRows.SerializedBinaryRows holds the Avro block
else if oResponse.ArrowRecordBatch.RowCount > 0 then
// oResponse.ArrowRecordBatch.SerializedRecordBatch holds the Arrow batch
finally
oResponse.Free;
end;
end;
Formati di riga Avro e Arrow
BigQuery non restituisce le righe come campi già analizzati sul filo. Restituisce blocchi serializzati in uno di due formati colonnari e scegli il formato quando crei la sessione. Con DataFormat := 1 la risposta porta AvroRows, il cui campo SerializedBinaryRows contiene un blocco codificato in Avro e RowCount ti dice quante righe contiene. Con DataFormat := 2 la risposta porta un ArrowRecordBatch, il cui campo SerializedRecordBatch contiene un record batch Apache Arrow. Decodifichi il blocco con la tua libreria Avro o Arrow preferita. Lo schema della sessione, restituito insieme agli stream, descrive i nomi e i tipi delle colonne così sai cosa contiene ciascun blocco.
Filtrare e proiettare
Non devi leggere righe intere. La read session porta un oggetto ReadOptions che ti permette di spingere una proiezione e un filtro fino a BigQuery così invia meno dati. Aggiungi i nomi delle colonne a SelectedFields per proiettare solo le colonne di cui hai bisogno e imposta RowRestriction a un predicato in stile SQL per filtrare le righe lato server prima che vengano trasmesse.
oRequest.ReadSession.ReadOptions.SelectedFields.Add('name');
oRequest.ReadSession.ReadOptions.SelectedFields.Add('state');
oRequest.ReadSession.ReadOptions.RowRestriction := 'state = "CA"';
Disponibilità
Il client gRPC BigQuery fa parte dell'edizione Enterprise di sgcWebSockets e gira su Windows, macOS, Linux, iOS e Android. Un esempio pronto all'uso, con il loader dell'account di servizio e il flusso create-session e read-rows mostrato sopra, è in Demos\21.GRPC\16.BigQuery. Il riferimento completo, inclusi gli altri client gRPC di Google Cloud, è sulla pagina prodotto gRPC Client.
Domande o feedback? Contattaci. Riceverai una risposta dalle persone che hanno scritto il codice.
