DQLを使ってDynamoDBをSQL操作する
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/