この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWS には NoSQL データベース DynamoDBが存在します。 標準では
- ウェブ管理画面
- AWS CLI
- SDK を使ったプログラム
から操作することもでるものの、地味に面倒です。 今回は DQL を使ってシェルインターフェースから DynamoDB を SQL 操作する方法を紹介します。
DQL とは?
DQL は "DynamoDB Query Language" の略で DynamoDB 向けの SQL 風インターフェースです。
DynamoDB テーブルの作成・更新・削除からレコードの追加・参照・更新・削除を SQL 風に操作できます。
サクッと DynamoDB の中を覗く場合には、今回紹介するようなツールを使うのがお手軽ではないかと思います。
インストール
DQL は Python で書かれているため pip でインストールします。
$ pip install -U dql
$ dql --version
0.5.22
SQL 実行方法
SQL の実行方法は
- シェル
- コマンドライン
の2通りがあります。
シェルから SQL を実行
シェル起動時にリージョンを指定します。たとえば日本リージョンの場合は次のようになります。
$ dql -r ap-northeast-1
ap-northeast-1>
リージョンを指定しなかった場合は N. Virginia に接続します。
$ dql
us-west-1>
環境変数 AWS_REGION が設定されている場合は、そのリージョンが優先されます。
$ export AWS_REGION=ap-northeast-1
$ dql
ap-northeast-1>
以降の例ではシェルモードから SQL を実行します。
コマンドライン から SQL を実行
sql -c
に続けて SQL を投げます。
$ dql -c 'SCAN * FROM Movies'
シェルと同じ要領でAWSリージョンを指定します。例えば、東京リージョンに対して SQL を投げる場合は次のようになります。
$ dql -r ap-northeast-1 -c 'SCAN * FROM Movies'
以下ではシェルモードで操作します。
テーブルの作成
CREATE
文でテーブルを作成します。
eu-central-1> CREATE TABLE Movies (
> year NUMBER HASH KEY,
> title STRING RANGE KEY,
> THROUGHPUT (10, 10));
Created table 'Movies'
eu-central-1> ls
Name Status Read Write
Movies ACTIVE 10 10
DUMP
文でテーブルスキーマを確認できます。
リージョン内の全テーブル
eu-central-1> DUMP SCHEMA;
CREATE TABLE Movies (year NUMBER HASH KEY, title STRING RANGE KEY, THROUGHPUT (10, 10));
リージョン内の特定のテーブル
eu-central-1> DUMP SCHEMA Table1,Table2;
...;
アイテムの作成
INSERT
文でアイテムを作成します。
eu-central-1> insert into Movies(
> year=2015,
> title="The Big New Movie",
> info={
> "plot": "Nothing happens at all.",
> "rating" : 0});
Inserted 1 item
アイテムの参照
DynamoDB テーブルのスキャンには SCAN
文を使用します。。
eu-central-1> SCAN * FROM Movies;
-----------------------------------------------------------------------------------------------
| info | title | year |
-----------------------------------------------------------------------------------------------
| {u'plot': u'Nothing happens at all.', u'rating': Decimal('0')} | 'The Big New Movie' | 2015 |
-----------------------------------------------------------------------------------------------
DynamoDB テーブルのクエリーには SELECT
文を使用します。。
eu-central-1> SELECT * FROM Movies WHERE year=2015;
-----------------------------------------------------------------------------------------------
| info | title | year |
-----------------------------------------------------------------------------------------------
| {u'plot': u'Nothing happens at all.', u'rating': Decimal('0')} | 'The Big New Movie' | 2015 |
-----------------------------------------------------------------------------------------------
インデックスを指定せずにテーブル全体を SELECT
しようとすると、以下のようなエラーが発生します。
eu-central-1> SELECT * FROM Movies;
...
SyntaxError: No index found for query. Please use a SCAN query, or set allow_select_scan=True
opt allow_select_scan true
一つ前の例のようにSCAN
文を使うか、次のように allow_select_scan
オプションを変更します。
# 現在のオプションを確認
eu-central-1> opt allow_select_scan
allow_select_scan: False
# オプションを変更
eu-central-1> opt allow_select_scan true
# 現在のオプションを確認
eu-central-1> opt allow_select_scan
allow_select_scan: True
# テーブル全体を SELECT
eu-central-1> SELECT * FROM Movies;
-----------------------------------------------------------------------------------------------
| info | title | year |
-----------------------------------------------------------------------------------------------
| {u'plot': u'Nothing happens at all.', u'rating': Decimal('0')} | 'The Big New Movie' | 2015 |
-----------------------------------------------------------------------------------------------
アイテムの更新
UPDATE
文でアイテムを更新します。
UPDATE
式には AWS ドキュメントにある式を使えます。
実際に info
属性を変更してみましょう。
eu-central-1> UPDATE Movies
> SET info.rating = 5.5, info.plot= "Everything happens all at once.", info.actors= ["Larry", "Moe", "Curly"]
> WHERE year = 2015 AND title = "The Big New Movie";
Updated 1 item
eu-central-1> SCAN * FROM Movies;
--------------------------------------------------------------------------------------------------------------------------------------------------
| info | title | year |
--------------------------------------------------------------------------------------------------------------------------------------------------
| {u'plot': u'Everything happens all at once.', u'actors': [u'Larry', u'Moe', u'Curly'], u'rating': Decimal('5.5')} | 'The Big New Movie' | 2015 |
--------------------------------------------------------------------------------------------------------------------------------------------------
無事変わっていますね。
アイテムの削除
DELETE
文でアイテムを削除します。
eu-central-1> DELETE FROM Movies WHERE year=2015 AND title="The Big New Movie";
Deleted 1 item
WHERE
を指定しなければ、テーブル全体を削除してしまうため、更新前に確認が求められます。
eu-central-1> DELETE FROM Movies;
This will run delete_item on all items in the table! Continue? [y/N] y
Deleted 1 item
eu-central-1> SCAN * FROM Movies;
No results
アイテムのファイル入出力
ファイル出力
SELECT
文に SAVE
オプションを渡すと、ファイル出力できます。
eu-central-1> SELECT * FROM Movies SAVE Movies.json;
Saved 1 record to Movies.json
出力されたファイルの中身を確認してみましょう。
$ cat Movies.json
{"info":{"plot":"Everything happens all at once.","actors":["Larry","Moe","Curly"],"rating":5.5},"title":"The Big New Movie","year":2015}
デフォルトでは Python の Pickle 形式でシリアライズされます。
.csv, .json, .gz, .gzip などを出力ファイル名に含めると、それぞれの形で展開されます。
バイナリーデータなどが含まれる場合、 .csv, .json 出力すると、正しく出力されないため、お気をつけ下さい。
ファイル入力
LOAD
文でファイルからアイテムを投入できます。
eu-central-1> LOAD Movies.json INTO Movies;
Loaded 1 item
DynamoDB へのクエリー文の確認
EXPLAIN
文で SQL がどういうクエリーに展開されるのか確認できます。
eu-central-1> EXPLAIN SELECT * FROM Movies WHERE title = "The Big New Movie" and year = 2015;
query {'ConsistentRead': False,
'ExpressionAttributeNames': {'#f1': 'year'},
'ExpressionAttributeValues': {':v1': {'S': u'The Big New Movie'},
':v2': {'N': u'2015'}},
'KeyConditionExpression': u'(title = :v1 AND #f1 = :v2)',
'ReturnConsumedCapacity': 'INDEXES',
'ScanIndexForward': True,
'TableName': 'Movies'}
テーブルの削除
DROP
文でテーブルを削除します。
# テーブル一覧を確認
eu-central-1> ls
Name Status Read Write
Movies ACTIVE 10 10
# テーブルを削除
eu-central-1> DROP TABLE Movies;
Dropped table 'Movies'
# テーブル一覧を確認
eu-central-1> ls
Name Status Read Write
まとめ
今回は DQL を使ってシェルインターフェースから DynamoDB を SQL 操作する方法を紹介しました。 類似ツールに @winebarrel さん作成の ddbcli があります。
DQL と ddbcli が目指すところや機能に大きな差はありませんが、DQL はドキュメントがしっかりしている点が優位かなと思います。
DynamoDB を SQL 操作したい場合は ddbcli だけでなく DQL も一度検討されてはいかがでしょうか。
参考
- PyPI https://pypi.python.org/pypi/dql
- GitHub : https://github.com/stevearc/dql
- Document : http://dql.readthedocs.io/en/latest/