Screaming Loud

日々是精進

scalaのクエリビルダー「quill」を使ってみた

takezoeさんがquillを紹介していたので、
Scalaの新しいデータベースアクセスライブラリ「quill」を試してみた - たけぞう瀕死ブログ
実際にどんな感じで使えるのかを試してみました。

http://getquill.io/getquill.io

結論、Slick2系から置き換えるのはなかなかありかなと思っています。

直接的なクエリサンプルは、上記のtakezoeさんのブログやドキュメントに書いてあるので、もうちょっと踏み込んだ内容を紹介したいと思います。

Database Access

今回は自分がよく使うMySQLにアクセスするように試しました。

動かすのに必要な最低限のlibraryは以下です。

libraryDependencies ++= {
  Seq(
    "mysql"       %  "mysql-connector-java" % "5.1.36",
    "io.getquill" %% "quill-jdbc" % "0.4.2-SNAPSHOT",
    "com.zaxxer" % "HikariCP" % "2.4.3",
    "com.typesafe" % "config" % "1.3.0"
  )
}

HikariCPとTypesafeConfigがないと、動きません。
また、このバージョンの場合、Java8でないと動きません。

build.sbtを上記のように作って上げれば、ドキュメントに書いてあるようなクエリをコンパイルすることができます。
quill_example/UserDao.scala at master · moc-yuto/quill_example · GitHub

テーブル名

Slickと違ってテーブル名を文字列で指定する部分はなく、queryのcase classがそのままテーブル名に使われます。

以下の例だと、case classのUsersがそのままテーブル名として使われます。

case class Users(id: Int, name: String, age: Int)

val find = quote { (id: Int) =>
  query[Users].filter(u => u.id == id)
}

トランザクション

やはり、実践投入するならトランザクション処理は必須となりますが、本家ドキュメントには書かれていません。
しかし、テストコードにはしっかり書かれています。

書き方としてはとても単純で、以下のようにtransaction関数でくくってあげればいいだけです。

db.transaction{
  val a = db.run(UserDao.findName)(name).headOption
  if (a.isEmpty) db.run(UserDao.insert)(name, age)
  else db.run(UserDao.update)(a.get.id, age)
  throw new Exception
}

このように書くと以下の様なクエリが流れました。

2016-03-06T15:29:28.783495Z   13 Query  SET autocommit=1
2016-03-06T15:29:28.783727Z   13 Query  set session transaction read write
2016-03-06T15:29:28.783987Z   13 Query  SELECT @@session.tx_isolation
2016-03-06T15:29:28.828915Z    4 Query  SELECT x1.id, x1.name, x1.age FROM users x1 WHERE x1.name = 'aaa'
2016-03-06T15:29:28.875733Z    4 Query  select @@session.tx_read_only
2016-03-06T15:29:28.877008Z    4 Query  select @@session.tx_read_only
2016-03-06T15:29:28.877849Z    4 Query  UPDATE users SET age = 1323 WHERE id = 2
2016-03-06T15:29:28.890415Z    4 Query  rollback
2016-03-06T15:29:28.891274Z    4 Query  SET autocommit=1

実際のトランザクションのコードは以下です。
quill_example/Users.scala at master · moc-yuto/quill_example · GitHub

感想

Slickよりも冗長な部分が減ったな―と感じます。
それでいてSlick風な書き方なので、書きやすいと思います。
また、Slickでは生成できないSQLを作れるDSLが多数あるので、細かいハンドリングがしやすいと感じました。


以下は動かしたサンプルです。
github.com

早速githubのPRテンプレート機能を使ってみた。

GithubのPRテンプレート機能が出たということで、試しに使ってみた。

何が追加されたか?

GithubのIssueとPRのテンプレートができた。

PRはデフォルトでこんな感じで表示される
f:id:yuutookun:20160218094334p:plain

まあ普通のテンプレートですね。

どうやって使うのか?

プロジェクトのルートディレクトリか.githubフォルダに以下を格納することでできます。

.github
  └ PULL_REQUEST_TEMPLATE.md # PRのテンプレート
 └ ISSUE_TEMPLATE.md # Issueのテンプレート
 └ CONTRIBUTING.md # PR時の注意書き

簡単ですね。

これを利用して、さらにGithubライフを充実させていきましょう。


参考リポジトリはこちら
GitHub - moc-yuto/regression: calculate regression by breeze

Hadoop Spark Conference Japan 2016 に参加したときのメモ

Hadoop Spark Conference Japan 2016に参加したので、その聞いた内容をまとめました。

Spark MLlib Now and Beyond

Spark自体はコントリビュータが多いプロダクト

sparkでは、2つのの機械学習ライブラリがある。

  • spark.mllib: RDDというデータフレームを利用
  • spark.ml: DataFrame, PipelineAPIを利用

spark.mlの利用を推奨
scikit-learnに影響

【データ構造】
  • RDD
  • DataFrameAPI

RDD
numpy.arrayのような配列の形式

【DataFrameAPI】
DataFrameAPI:RDBのように直感的にデータにアクセスできるAPI
pandasに影響を受けて作られている

サポートしているデータソースも豊富
jdbc, mysql, posqresql, hive

ビルトイン関数も豊富
Catalystによる処理最適化によって、生RDDよりDataFrameのほうが速い

【PipelineAPI】

処理をつなげられ、再利用もしやすい

tokenizer:単語のトークン化
hashingTF:単語のベクトル化
logisticRegression:ロジスティック回帰

上の3つの操作をpipelineでまとめることができる

pipelineを再利用することで簡単に使い回すことができる
例えば、入力をtrainDataとtestDataにしたり。

pipelineを使うと
クロスバリデーションも簡単にできる

そしてその作ったpipelineをs3やhdfsに永続化することもできる

pythonで分析して、scalaで読み込む
なんてこともできる

【Mllib2.0】
・GLMの改善
・永続化未対応ライブラリがまだある。それの改善。

SparkによるGISデータを題材として時系列データ

GISデータとは、船の航行データ(緯度、輝度、速度とか)
GISデータ、センサーデータ:多変量時系列データ
データの収集・蓄積はできているが、分析がまだまだ。

【要件】
性能、柔軟性、スケーラビリティが必要

【sparkを用いた時系列データ処理】

時間依存の情報
・時刻
・緯度、経度
時間非依存の情報
・移動体ID

やりたいこと
・移動体ごとにデータをソート
・時刻や座標の差分を計算
・numpyの関数をそのまま使えること

時系列データの評価ポイント

  1. レコード長の違い:長いほうが遅い(普通)
  2. レコードに偏りをもたせるか:ほぼ変わらない
  3. RDDかDataFrameか:DataFrameのほうが速い

RDD [“ships”, “0.0.0"]
DataFrame は表形式
ただ、DataFrameはメモリを使うので、そこら辺のチューニングが必要

flinkとかも出てきている。
pythonでできるところは、pythonで。

行、列指向の片方だけで閉じない

なんでpythonから移行したのか?→データ量が増えてきて、今後に対応できないと感じたから
sparkは1台で実行したのか?→並列で実行させている

sparkUIから確認することで、チューニングを行った。

時系列データにSparkを使うのは現実としてあり。

まだまだ、公式には足りない機能が多いので、spark packagesなどのパッケージ関連を検索してみるのも大事。

Hive on Sparkを活用した高速データ分析

CDHをいれていると、3clickでHive on Sparkが導入可能に。

www.slideshare.net

最短でsbtのコマンドを追加する方法

sbtと打つとREPLが起動し、runしたりtestが走らせられたり色んな挙動をさせられる。

しかし、自分でコマンドを作ろうと調べてみると、案外出てこない。

ということで最短でコマンド作成を紹介します。

最短でHelloという文字を出力させる

Helloという文字列を出力させます。

build.sbtに以下を記載します。

これで以下出力が出せます。

$sbt
>hello
Hello
[success] Total time: 0 s

別ファイルに定義したメソッドを呼ぶ

こちらの方がニーズがあるでしょう。

project/Hello.scalaを作ります。

先ほどと同じようにbuild.sbtに以下を記載します。

このように出力できます。

$sbt
>hello
Hello
[success] Total time: 0 s

sbt REPL上で引数を受け取るタスク

こうやると、引数を受け取れます。

$ sbt
> hello
List()
[success] Total time: 0 s, completed 2016/02/05 19:47:46
> hello a
List(a)
[success] Total time: 0 s, completed 2016/02/05 19:47:49
>