diff --git a/docs/jdbc.md b/docs/jdbc.md index 8f8b76478..b57accfe3 100644 --- a/docs/jdbc.md +++ b/docs/jdbc.md @@ -9,18 +9,54 @@ First start PGAdapter: ```shell wget https://storage.googleapis.com/pgadapter-jar-releases/pgadapter.tar.gz && tar -xzvf pgadapter.tar.gz -java -jar pgadapter.jar -p my-project -i my-instance -d my-database +java -jar pgadapter.jar -p my-project -i my-instance ``` -Connect to PGAdapter like this: +Connect to PGAdapter using TCP like this: ```java // Make sure the PG JDBC driver is loaded. Class.forName("org.postgresql.Driver"); // Replace localhost and 5432 with the host and port number where PGAdapter is running. -// prepareThreshold=0 disables the use of server-side prepared statements in JDBC. -try (Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/?prepareThreshold=0")) { +try (Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/my-database")) { + try (ResultSet resultSet = connection.createStatement().executeQuery("select 'Hello world!' as hello")) { + while (resultSet.next()) { + System.out.printf("Greeting from Cloud Spanner PostgreSQL: %s\n", resultSet.getString(1)); + } + } +} +``` + + +### Unix Domain Sockets +Connect to PGAdapter using Unix Domain Sockets like this: + +Add this to your dependencies: +```xml + + com.kohlschutter.junixsocket + junixsocket-core + 2.5.0 + pom + + + com.kohlschutter.junixsocket + junixsocket-common + 2.5.0 + +``` + +```java +// Make sure the PG JDBC driver is loaded. +Class.forName("org.postgresql.Driver"); + +// '/tmp' is the default domain socket directory for PGAdapter. This can be changed using the -dir +// command line argument. 5432 is the default port number used by PGAdapter. Change this in the +// connection string if PGAdapter is running on a custom port. +try (Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost/my-database" + + "?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg" + + "&socketFactoryArg=/tmp/.s.PGSQL.5432")) { try (ResultSet resultSet = connection.createStatement().executeQuery("select 'Hello world!' as hello")) { while (resultSet.next()) { System.out.printf("Greeting from Cloud Spanner PostgreSQL: %s\n", resultSet.getString(1)); @@ -33,3 +69,39 @@ try (Connection connection = DriverManager.getConnection("jdbc:postgresql://loca This example uses the pre-built jar to run PGAdapter as a standalone process. See [README](../README.md) for more possibilities on how to run PGAdapter. + +## Performance Considerations + +The following will give you the best possible performance when using the JDBC driver with PGAdapter. + +### Unix Domain Sockets +Use Unix Domain Socket connections for the lowest possible latency when PGAdapter and the client +application are running on the same host. See https://jdbc.postgresql.org/documentation/head/connect.html +for more information on connection options for the JDBC driver. + +### JDBC Batching +Use the JDBC batching API when executing multiple DDL or DML statements. PGAdapter will combine +DML and DDL statements that are executed in a JDBC batch into a single request on Cloud Spanner. +This can significantly reduce the overhead of executing multiple DML or DDL statements. + +Example for DML statements: + +```java +try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch("insert into my_table (key, value) values ('k1', 'value1')"); + statement.addBatch("insert into my_table (key, value) values ('k2', 'value2')"); + // This will execute the above statements as a single batch DML request on Cloud Spanner. + int[] updateCounts = statement.executeBatch(); +} +``` + +Example for DDL statements: + +```java +try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch("create table singers (singerid varchar primary key, name varchar)"); + statement.addBatch("create index idx_singers_name on singers (name)"); + // This will execute the above statements as a single DDL update request on Cloud Spanner. + int[] updateCounts = statement.executeBatch(); +} +```