Anwendungen mit GoogleSQL für Bigtable entwickeln
Mit GoogleSQL für Bigtable können Sie Abfragen aus Ihren Anwendungen ausführen, um Rechenfunktionen an Bigtable auszulagern. Dadurch ist weniger clientseitige Verarbeitung erforderlich. GoogleSQL ist eine ANSI-konforme strukturierte Abfragesprache, die für Bigtable und andere Google Cloud -Dienste implementiert wurde. Weitere Informationen zu anderen Anwendungsfällen von GoogleSQL für Bigtable finden Sie unter GoogleSQL für Bigtable – Übersicht.
Hinweis
Die müssen Folgendes haben:
- Eine Bigtable-Instanz und ‑Tabelle.
- Die Bigtable-Clientbibliothek für Ihre Sprache. Weitere Informationen zum Installieren und Verwenden von Clientbibliotheken für Bigtable finden Sie unter Bigtable-Clientbibliotheken.
- Die Authentifizierung wird über Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC) eingerichtet. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.
Beispielszenario
In den Beispielen in diesem Leitfaden wird eine weather-data-Beispieltabelle verwendet, auf die Sie über Ihre kostenlose Testinstanz in derGoogle Cloud -Konsole zugreifen können. Angenommen, in Ihrer Tabelle werden Informationen von verschiedenen Wetterstationen gespeichert, die durch ein station_id gekennzeichnet sind. Jede Station erfasst die Temperatur in Grad Fahrenheit in einer Spalte mit dem Namen temp_f. Anstatt die Temperatur in Ihrer Anwendung zu berechnen, können Sie eine SQL-Abfrage verwenden, um diese Temperaturen direkt in Bigtable in Grad Celsius umzurechnen, bevor Sie die Ergebnisse an Ihre Anwendung zurücksenden. Weitere Informationen zum Abfragen der Wetterdatentabelle finden Sie unter Beispieldaten abfragen.
Best Practices
Beachten Sie die folgenden Best Practices, um die Leistung und Ressourcennutzung zu optimieren, wenn Sie Anwendungen entwickeln:
- Client wiederverwenden:Erstellen Sie einen einzelnen
BigtableDataClientfür Ihre Anwendung. Der Client übernimmt die Verwaltung von gRPC-Kanälen und ist auf hohe Parallelität ausgelegt. Wir empfehlen, diesen Client einmal nach dem Starten Ihrer Anwendung zu erstellen und dann für jede Anfrage wiederzuverwenden. - Parametrisierte Abfragen verwenden:Verwenden Sie
PreparedStatement, um die Abfragelogik von Datenwerten zu trennen. Dadurch kann Bigtable den Ausführungsplan im Cache speichern und SQL-Injection verhindern. - Vorbereitete Anweisungen wiederverwenden:Rufen Sie
PreparedStatementnur einmal pro SQL-String auf. Die Anweisung speichern und für mehrere Anfragen wiederverwenden.
Bigtable-Client erstellen
Erstellen Sie eine BigtableDataClient, um die Verbindung zwischen Ihrer Anwendung und Bigtable zu verarbeiten. Im folgenden Beispiel wird gezeigt, wie Sie eine einzelne Clientinstanz in Ihrer Anwendung freigeben, um Verbindungen effizient zu verwalten:
BigtableDataSettings settings = BigtableDataSettings.newBuilder()
.setProject(PROJECT_ID)
.setInstance(INSTANCE_ID)
.build();
// The client is thread-safe and should be reused.
try (BigtableDataClient dataClient = BigtableDataClient.create(settings)) {
System.out.println("Connected to: " + INSTANCE_ID);
}
Abfrage vorbereiten
Anstatt Ihre Daten direkt in einen SQL-String einzufügen, empfehlen wir, parametrisierte Abfragen zu verwenden. In GoogleSQL für Bigtable entsprechen parametrisierte Abfragen einer vorbereiteten Anweisung. So können Sie die Abfragelogik von den Datenwerten trennen.
Im folgenden Beispiel sehen Sie, wie Sie Ihre GoogleSQL-Abfrage mit Parameterplatzhaltern wie @sid definieren. Erstellen Sie dann eine PreparedStatement, indem Sie den SQL-String und die Typen für jeden Parameter angeben, damit die Abfrage beim nächsten Mal schneller ausgeführt werden kann:
Map<String, SqlType<?>> paramTypes = new HashMap<>();
paramTypes.put("sid", SqlType.string());
String sql = "SELECT " +
"ROUND((CAST(CAST(weather['temp_f'] AS STRING) AS INT64) - 32) * 5 / 9, 2) AS temp_celsius " +
"FROM " + TABLE_NAME + " WHERE station_id = @sid LIMIT 1";
// Create and reuse the PreparedStatement.
PreparedStatement preparedStatement = dataClient.prepareStatement(sql, paramTypes);
Abfrage ausführen
Geben Sie Parameterwerte an und führen Sie die Abfrage aus. Im folgenden Beispiel wird gezeigt, wie Sie mit PreparedStatement Werte an Ihre Parameter binden, um ein BoundStatement zu erstellen. Anschließend wird die Abfrage ausgeführt und die Ergebnisse werden durchlaufen, um ResultSet auszugeben, die Temperatur in Grad Celsius:
BoundStatement boundStatement = preparedStatement.bind()
.setStringParam("sid", stationId)
.build();
try (ResultSet resultSet = dataClient.executeQuery(boundStatement)) {
while (resultSet.next()) {
System.out.println("Temp: " + resultSet.getDouble("temp_celsius"));
}
}
Datenstruktur prüfen
Wenn Sie SQL entwickeln oder untersuchen, empfehlen wir, die mit der Tabelle verknüpften Metadaten zu prüfen, um die Datenstruktur zu verstehen. Da Bigtable ein flexibles Schema hat, können sich Ihre Abfrageergebnisse bei Verwendung von SELECT *-Abfragen je nach Daten ändern. Daher empfehlen wir, keine SELECT *-Abfragen in Produktionsanwendungen zu verwenden.
Im folgenden Beispiel werden die Metadaten des Ergebnissatzes (z. B. die Spaltennamen und -typen) untersucht und dann unabhängig von den Daten an den Client zurückgesendet. So können Sie zuerst die Spalteninformationen abrufen und dann die Datenstruktur erstellen, die Sie zum Verarbeiten der Daten in der Anwendung benötigen.
ResultSetMetadata metadata = resultSet.getMetadata();
System.out.print("Columns: ");
metadata.getColumnsList().forEach(col -> System.out.print(col.getName() + " "));
System.out.println();
Mit Spaltenfamilien arbeiten
Bigtable speichert Daten in Spaltenfamilien. GoogleSQL gibt diese Familien als Listen von Namen und Werten zurück, die als Maps von Spaltenqualifizierern und ‑werten bezeichnet werden. Beim Lesen einer Spaltenfamilie gibt Bigtable den Typ SqlType.Map zurück. Wenn Sie eine Spaltenfamilie aus einer Tabelle mit Verlauf lesen, z. B. SELECT column FROM my_table(with_history=>true), gibt Bigtable den Typ SqlType.historicalMap() zurück. Das ist eine Zuordnung von Spaltenqualifizierern und einem Array von Zellen-Zeitstempeln und ‑Werten. Weitere Beispiele für SqlType-Typen finden Sie unter SqlType.
Im folgenden Beispiel wird gezeigt, wie Sie anstelle von jeweils einer Spalte eine ganze Gruppe von Spalten gleichzeitig abrufen können. Im Code wird die Spaltenfamilie in einer Map gespeichert, sodass Sie alle Namen und Werte durchlaufen können:
Map<String, SqlType<?>> paramTypes = new HashMap<>();
paramTypes.put("keyPrefix", SqlType.bytes());
String sql = String.format("SELECT weather FROM %s WHERE STARTS_WITH(_key, @keyPrefix)", TABLE_NAME);
PreparedStatement preparedStatement = dataClient.prepareStatement(sql, paramTypes);
BoundStatement boundStatement = preparedStatement.bind()
.setBytesParam("keyPrefix", ByteString.copyFromUtf8(key))
.build();
try (ResultSet resultSet = dataClient.executeQuery(boundStatement)) {
while (resultSet.next()) {
SqlType.Map<ByteString, ByteString> mapType = SqlType.mapOf(SqlType.bytes(), SqlType.bytes());
Map<ByteString, ByteString> weatherValues = resultSet.getMap("weather", mapType);
for (Map.Entry<ByteString, ByteString> entry : weatherValues.entrySet()) {
System.out.printf("%s = %s\n",
entry.getKey().toStringUtf8(),
entry.getValue().toStringUtf8());
}
}
}
Nächste Schritte
- GoogleSQL für Bigtable – Referenzdokumentation
- Informationen zum Schreiben von SQL mit Gemini-Unterstützung