BigQueryでクライアントライブラリを利用してデータをSELECTする

Google BigQueryでは、テーブルからデータを取得する方法として以下の2つがあります。

* クライアントライブラリを利用して取得する方法
* APIを利用して取得する方法

本記事では、「クライアントライブラリを利用して取得する方法」を紹介します。

### 環境
*  クライアントライブラリ：0.32.0-beta
*  java：8

### 環境構築
[BigQueryのクライアントライブラリのインストール](https://cloud.google.com/bigquery/docs/reference/libraries?hl=ja)を参照。
2018年1月時点で、javaのクライアントライブラリはbeta版しかないので、本記事でもそれを利用します。なお、クライアントライブラリのソースは以下で公開されています。
https://github.com/GoogleCloudPlatform/google-cloud-java/tree/master/google-cloud-bigquery

### テーブル構成
本記事では、以下の構成のテーブルに対してSELECTします。

* データセット名：dev1
* テーブル名：names_2014
* スキーマ情報：以下の通り

|COLUMN|TYPE|MODE|
|---|---|---|
|name|STRING|NULLABLE|
|gender|STRING|NULLABLE|
|count|INTEGER|NULLABLE|

### listTableDataメソッドを利用する
BigQuery#listTableDataを利用します。

```BigQuerySelectSample.java
package bigquery.sample;

import com.google.api.gax.paging.Page;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.FieldValueList;

public class BigQuerySelectSample {

	private static final String DATASET_NAME = "dev1";
	private static final String TABLE_NAME = "names_2014";
	private static final int NAME_COLUMN = 0;
	private static final int GENDER_COLUMN = 1;

	public static void main(String[] args) {

		BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

		// use listTableData method
		Page<FieldValueList> tableData = bigquery.listTableData(DATASET_NAME, TABLE_NAME);
		for (FieldValueList row : tableData.iterateAll()) {
			System.out.println(row.get(NAME_COLUMN).getValue() + " " + row.get(GENDER_COLUMN).getValue());
		}
	}
}

```

listTableDataメソッドは、スキーマ情報(カラム名等)は返さずデータのみを返します。そのため、ある特定のカラムのデータが必要な時は、row.get(0)、row.get(1)のように、rowのindexでアクセスする必要があります。

### queryメソッドを利用する
BigQuery#listTableDataの他に、BigQuery#queryを利用することもできます。

```BigQuerySelectSample.java
package bigquery.sample;

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.FieldValueList;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.QueryResponse;

public class BigQuerySelectSample {

	private static final String DATASET_NAME = "dev1";
	private static final String TABLE_NAME = "names_2014";

	public static void main(String[] args) throws InterruptedException {

		BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

		// use query method
		String query = "SELECT name, gender FROM `" + DATASET_NAME + "." + TABLE_NAME + "` WHERE name = 'Ryder'";
		QueryJobConfiguration queryConfig = QueryJobConfiguration.of(query);
		QueryResponse response = bigquery.query(queryConfig);
		for (FieldValueList row : response.getResult().iterateAll()) {
			System.out.println(row.get("name").getValue() + " " + row.get("gender").getValue());
		}
	}
}
```

BigQueryでもRDBと同じような形式でSQLを書くことができます。なお、詳細なクエリリファレンスは[BigQueryのSELECT句](https://cloud.google.com/bigquery/query-reference?hl=ja#select)になります。queryメソッドは、スキーマ情報(カラム名等)も返してくれるので、row.get("columnName")のようにカラム名でのアクセスが可能となります。

### パフォーマンス
簡易計測になりますが、33206件のテーブルに対してBigQuery#listTableData、BigQuery#queryともに約4~5秒でした。両者ともにそこまで大差はなさそうです。

以上です。

### 参考
* [Interface BigQuery](https://googlecloudplatform.github.io/google-cloud-java/0.32.0/apidocs/index.html)
* [BigQueryのjavadoc](https://googlecloudplatform.github.io/google-cloud-java/0.32.0/apidocs/index.html)
* [BigQueryのSELECT句](https://cloud.google.com/bigquery/query-reference?hl=ja#select)