About Me

My photo
Software Engineer at Starburst. Maintainer at Trino. Previously at LINE, Teradata, HPE.

2018-02-01

Don't Stop The Query

昨日かなり重いクエリを流して帰り、今朝出社してから負荷を確認したところ400本近いクエリが遅延している状況を目の当たりにした私です。月初にやるべきではなかったなぁと反省しております。
さて、Teradataの製品群にAster AppCenterというソフトウェアがあるのですが、この製品はSQLとJavaでクエリの実行やグラフの可視化を行うことができます。 今のところ基本的にはSQLで書き、クエリをダイナミックに書き換えたいときなどはJavaを使っているのですが、とあるプロジェクトでデータがロードされていなかったら処理を失敗させたいという絶妙な要望があがりました。Javaなら簡単にかけますが、そのためだけに使いたいかというとうーん…となる感じですね。ちなみにSQLでもJavaでも1つの入力フォームしかないので、1つ目の処理が正常終了したら次へみたいなレベルの処理をちゃんとやりたい場合にはJavaで書く必要があります。
帰りの電車で反省中に思いついたのが、サブクエリでcountをとってcaseでわざとランタイムエラーを発生させるという方法です。
特別な関数は使わないのでPrestoで試してみました。まずはテーブルの準備。

create table memory.default.log (
  id int,
  log_date date
)
;
insert into memory.default.log values (1, cast('2017-12-31' as date))
;

上の状態でまだロードの終わっていない日付、例えば2018/1/1に以下のクエリを実行すると、サブクエリ内のcntは0になり、case内の条件がtrueになりcastが実行されます。数値ではなく文字をintegerにキャストしようとするのでエラーになることが確認できます。

select
 case when cnt = 0 then cast('record not found' as integer) end c1
from
 (select count(*) as cnt from memory.default.log where log_date = current_date) t
;

ちなみにPrestoだと以下のようなエラーメッセージが出力されます。
Query 20180131_163346_00452_nyghj, FAILED, 1 node
Splits: 41 total, 40 done (97.56%)
0:00 [1 rows, 5B] [4 rows/s, 21B/s]
Query 20180131_163346_00452_nyghj failed: Cannot cast 'record not found' to INT

特殊な方法は使っていないので、ほとんどのRDBMSで適用できるんじゃないかなと思っています。ちゃんとしたジョブでやるのがベストではありますが、こういうトリッキーな方法や考え方はたまに役に立ったりするもんなので残しておきます。
タイトルはDon’t Stop The Music feat.森高千里をもじっているので最後にライブ映像を貼っておきます。みなさまどうぞご覧くださいませ。