SQL
slick
Elm
ZeneloDay 3

Slickが出すクエリをなんとかしようとした話


前置き

どうも、謎の集団Zeneloの中でSQLとか見てる人です。

普段、クエリレビューなどをして生きているのですが、Zeneloがメインで使っているSlickってやつが、これまたやんちゃな子で、時々おかしなSQLを出力するのです。

あ、Slickってやつは

http://slick.lightbend.com/

で、O/RMっぽいやつです。

(Slick本家的に言うとF/RM,functional-relational mapperらしく、O/RMではないって強く主張しているので、明日僕は殺されるかもしれない)


Slickが出してくれるクエリについて

規模の小さいプロダクトだと、多分Slickは何の問題もないのでしょう。

// priceが10未満で、name順にソートしたcoffeeの名前のみ取り出すクエリを作る

coffees.filter(_.price < 10.0).sortBy(_.name).map(_.name)
// select name from COFFEES where PRICE < 10.0 order by NAME

このクエリは公式ドキュメントから取ってきました。

ただScalaのコードをScalaらしく書くだけで、綺麗なクエリが出力されます。

さらに型チェックもされたり、インジェクションなどが起きないようになっていたりと、Scalaエンジニアにとって至れり尽くせりとなっています。

しかし、大規模な、4つか5つか以上のテーブルをINNER JOINなどで繋げようとした場合、変な現象が起きます。

ちょっとだけお見せすると、こちら。



スクリーンショット 2018-12-02 22.14.22.png

後述する自作ツールの出力結果なのですが、なかなか香ばしいことになってますよね。

Slickは、大きなクエリになれば、テーブルやカラム名を全て、「xの後に数字がつく (正規表現だと /x(\d)+/)」みたいなやつでどんどん置き換えていきます。

面白い仕組みではありますが、「x139.x152 = x184.x185」みたいなものを見せられて、何と何を比較しようとしているのかわかりません。

また、そのあと使わないのに、とりあえず置き換えとくみたいなことをしてくれるので、どこにも使われていない無駄な置き換えが出てきます。

このクエリがSlowQueryとして流れてきたときには、「どっからどう見ればいいんだ・・・」ってなってました。

(ちなみにこのSlowQueryは、整形ツールで見ると294行です。さらに言うと、x213まであります。なかなかの迫力ですよね。)

私はDBやSQLを見るためにこの集団に所属しているので、どんなSQLであっても、このSQLを見る必要があります。

とはいえ僕も一応エンジニア、数回は手で全部パースしてレビューしてってやってみたのですが、疲れたので自動化することにしました。


作ったツール

http://s.063.jp/index.html

個人で使うように作ったものなので、ほぼ何の機能もありません。

デザイン?なにそれおいしいの?って感じです。

ただ、asで言い換えているもののうち、使われていないものがあれば削除するだけです。

使い方は簡単で、「Query」ってところにSlickが出してきたクエリを入れると自動でSQLを見て、一度しか出てきていないものを検出してくれるので、チェックボックスを見て全部消しても良さそうなら「Execute」を押すだけです。

もし消しちゃダメな文にチェックボックスがついていればチェックボックスを外し、消してもいいのにチェックボックスがついてなければつけるだけです。

先ほど貼ったクエリもこのツールで見たものです。

例えば以下のように表示されたら、



スクリーンショット 2018-12-02 22.37.08.png

「x65.x74 as x75」の「x75」は他でも使われているから必要そうだけど、他のものは使われていなさそうだから消してもいい?

と言うことを表しています。

あとは「Execute」を押して、どんどん行数を減らしていきます。

最後に残るのは、本当に使われているものだけになります。

ちなみにこのクエリ、元を整形したものは294行ですが、このツールを通すことで出されたクエリは、同じ整形ツールで整形すると118行になりました🎉


このクエリのその後

整形したあと、本当に必要な部分だけをドメイン知識を持った人と改善していった結果、(同じ整形ツールで)22行になって、マージされ、今日も元気に動いています。

もちろんSlowQuery一覧からは消えて、利用者も開発者もハッピーになりました😁


Slickについての今後

流石に大きくなりすぎたプロダクトで、Slickで頑張っていくのは辛いよねって話になり、最近はPlainSQLに直してくれたりと、どんどん改善が続いています。

Slickが便利なところはSlickで、そうでないところはPlainSQLなどで、って方針でしばらくいくと思いますが、もしかしたらScalikeJDBCなどに載せ替えるかもしれません。(工数的にすごいことになりそうですけど・・・)


このツールの今後

今後プロダクトに入るクエリについては、もう安心できる程度にZeneloメンバーはSQLについて関心を持って開発していると思っているのですが、まだまだ「昔は(パフォーマンス的に)大丈夫だったけど、今後は・・・」ってクエリの改善活動が残っています。

そこでこのツールを使っていきます。不便だなって思ったら機能追加します。プルリクなども歓迎です。

リポジトリはここ。

https://github.com/Goryudyuma/slick-refactoring-tool

このツールは、謎の集団Zeneloで今ブームな言語、Elmで書かれています。

大魔王の力は絶大で、その力にあやかったので、このツールも「えいっ」てやればいつの間にかできてました。

ただ、まだ僕の力が足りず、正規表現で頑張っちゃったので、次同じようなツールを作るときは、きちんとParserでやりたいと思います。


最後に

この記事は謎の集団zeneloのアドベントカレンダーの三日目の記事として書かれました。

他の記事も是非よろしくお願いします。

https://qiita.com/advent-calendar/2018/zenelo