ASMのきもち

DBとAnsibleが気になって仕方ない人のブログ

TimesTenって知ってる?

f:id:tomomo1015:20191206110438p:plain

この記事は JPOUG Advent Calendar 2019 6日目の記事です。

改めて初めまして!Twitterではいつもお世話になっております⸜( ´ ꒳ ` )⸝
初ブログが Advent Calendar って大丈夫かな、とビクついてます。(他の方々が強すぎて怖い)
と怖がっていても仕方ないので、自分にできること、発信できることを記載したいなと思っています。

これからどうぞ、宜しくお願いします!

さて、今日はTimesTenという製品をちょっと紹介させてください。
長くなりそうなので、最初に結論を書きます。

Command> select count(*) from ORACLE.TEST_TABLE;
< 1655342 >
1 row found.
Execution time (SQLExecute + Fetch Loop) = 0.041723 seconds.

みてみて!めっちゃ早い!!!
(インメモリDBだから早いの当たり前とかいうの禁止/というか件数検索かい)


▼目次

TimesTenとは

TimesTenはTimesTen社が開発したインメモリDBです。
2005年にOracle社に買収された製品で、現在でも開発/販売されている製品です。
ラインナップ的にはOracleDBと同じ枠のよう(営業さんとか)、開発されてる場所もUS本社のDB棟です。

ざっくりいうと、機能が二つに分かれています。

  • TimesTen Classic
  • TimesTen ScaleOut (ちょっと前はVelocity Scaleって呼び名だった)

今回は前者の「TimesTen Classic」について記載します。というか、多分世界的にもこの使い方している人がほとんどなのではないかなと、個人的には思っています。
このClassicですが、昔は「Cache Connect」とか呼んでいた気がします。その名の通り、「参照先のOracleDBのデータを読み込んでメモリ上に展開する」機能が非常に優秀です。
製品のアーキテクト概要を以下に記載します。(いつもの雑絵ですいません)

f:id:tomomo1015:20191206114236p:plain

DBに更新された情報がどうやってTimesTenまでデータが伝搬されるのか、流れをざっくり記載します。

  1. 参照先のDBにデータが追加/更新される
  2. Triggerが実行されて、同じスキーマ内のTimesTen管理表に更新されたデータが格納される
  3. TimesTenのrefresherが定期的にOracleDB側のTimesTen管理表を検索、更新されたデータがあればそれをTimesTenサーバ側に持ってくる
  4. TimesTenサーバ側のメモリに展開&トランザクションログに更新情報を記載する

どんな場面で使うのか

一般論ですが、以下の場合はお勧めしています。

  • OLTP型のDBで、特にR>Wの傾向がある
  • Read性能に悩んでいる
  • 元々OracleDBを使っていて性能を上げるためにインメモリDBを使いたいが、KV型ではなくそのままSQLを使い続けたい
  • OSSではなく、メーカーサポートして欲しい

逆に、こんな場合はお勧めしていません。

  • DWH型、W>Rの傾向
  • DBのカラム変更やテーブル増減の頻度が激しい
  • ライセンス費かかるのなんて無理

メリデメ(個人の意見)

メリット
  • 早い。めちゃくちゃ早い。μsecで応答してくれるの凄い
  • 学習コストがやや低い。OracleDBと大体同じ操作(alter文とか)ができるし、PL/SQLも打てるので、特にOarcleDB知ってる人はすぐ覚える
  • DB更新データを自動で取ってきてくれるのが大変楽。作り込み不要
デメリット
  • OracleDB側のTable構成変えると、毎回全件データ読み込みし直しが運用的に辛い
  • 誰かがセッション繋いでいる状態だと、停止できない。アプリ側を毎度停止or片寄する運用が手間
  • これOSSにしてくれたらもっと流行ると思うんだけどなー?

結論、性能については◎なのですが、運用がちょっと△です。

使ってみる

こんなテーブルをOracleDBに作ってみました。

CREATE TABLE tomo
 (
 user_id VARCHAR2(128),
 user_name VARCHAR2(128),
 attribute VARCHAR2(512),
 CONSTRAINT pk1 PRIMARY KEY(user_id)
 ) 
TABLESPACE table_space;

ではこのテーブルのキャッシュを、TimesTenに作成します。

Command> create readonly cache group TTADM.TOMO_CACHE
       >    autorefresh
       >        mode incremental
       >        interval 6000 milliseconds
       >        /* state on */
       > from
       >    ORACLE.TOMO (
       >            USER_ID    VARCHAR2(128 BYTE) NOT INLINE ,
       >            USER_NAME  VARCHAR2(128 BYTE) NOT INLINE ,
       >            ATTRIBUTE  VARCHAR2(512 BYTE) NOT INLINE,
       >        primary key (USER_ID))
       >        unique hash on (USER_ID) pages = 4000;


細かい内容は割愛しますが、これでTimesTen側にキャッシュが作成されました。
これを、キャッシュグループと言います。キャッシュグループのステータスを確認してみましょう。

Command> cachegroups TTADM.TOMO_CACHE;

Cache Group TTADM.TOMO_CACHE:

  Cache Group Type: Read Only
  Autorefresh: Yes
  Autorefresh Mode: Incremental
  Autorefresh State: On
  Autorefresh Interval: 6 Seconds #6秒間隔でOracleDB側に問い合わせ
  Autorefresh Status: ok     
  Aging: No aging defined

  Root Table: ORACLE.TOMO
  Table Type: Read Only

1 cache group found.


不思議な感じですが、これでTABLEもできてます。(ReadOnlyですが)

Command> desc tomo;

Table ORACLE.TOMO:
  Columns:
   *USER_ID                         VARCHAR2 (128) NOT INLINE NOT NULL
    USER_NAME                       VARCHAR2 (128) NOT INLINE
    ATTRIBUTE                       VARCHAR2 (512) NOT INLINE

1 table found.
(primary key columns are indicated with *)

この時点では、OracleDB側もTimesTen側も、データ件数は0です。

Command>  select * from ORACLE.tomo;
0 rows found.

さて、ではここにデータを投入すると、どうなるでしょ?
OracleDB側にこんなデータを投入します。

INSERT ALL
INTO tomo VALUES ('k8s_1', 'koba-san', 'SumikoGurashi')
INTO tomo VALUES ('k8s_2', 'yoshi-san', 'CoreDQwalker')
INTO tomo VALUES ('k8s_3', 'vargo-san', 'NomalDQwalk')
INTO tomo VALUES ('k8s_4', 'cotco-san', 'Boss')
INTO tomo VALUES ('k8s_5', 'inductor-san', 'TSUYOI')
SELECT * FROM DUAL;

最近会った人シリーズ。言いたいことがある方は Twitterでお願いします。 ←

すると TimesTen側に…!

Command>  select * from ORACLE.tomo;
< k8s_1, koba-san, SumikoGurashi >
< k8s_2, yoshi-san, CoreDQwalker >
< k8s_3, vargo-san, NomalDQwalk >
< k8s_4, cotco-san, Boss >
< k8s_5, inductor-san, TSUYOI>
5 rows found.

データが入ってきますᐠ( ᐢ ᵕ ᐢ )ᐟ


じゃんじゃんOracleDBにデータ投入しますよ〜

INSERT ALL
INTO tomo VALUES ('MySQL_1', 'awache-san', 'Senior')
INTO tomo VALUES ('MySQL_2', 'yoshi-san', 'God')
INTO tomo VALUES ('MySQL_3', 'yamasaki-san', 'God2')
INTO tomo VALUES ('MySQL_4', 'sakai-san', 'GIS')
INTO tomo VALUES ('ansible_1', 'yokochi-san', 'TEKUNABE')
INTO tomo VALUES ('ansible_2', 'mofumofu-san', 'NANACHI')
INTO tomo VALUES ('ansible_3', 'tetematsu-san', 'TENKO')
INTO tomo VALUES ('ansible_4', 'zaki-san', 'OpenShiftMaster')
INTO tomo VALUES ('ansible_5', 'yascaim-san', 'NWmaster')
INTO tomo VALUES ('ansible_6', 'ippandansei-san', 'Climbing')
INTO tomo VALUES ('ansible_7', 'nakamura-san', 'ansible-BOSS')
SELECT * FROM DUAL;

値は特に気にしないでください。

TimesTen側を見ると…

Command> select * from ORACLE.tomo;
< k8s_1, koba-san, SumikoGurashi >
< k8s_2, yoshi-san, CoreDQwalker >
< k8s_3, vargo-san, NomalDQwalk >
< k8s_4, cotco-san, Boss >
< k8s_5, inductor-san, TSUYOI >
< MySQL_1, awache-san, Senior >
< MySQL_2, yoshi-san, God >
< MySQL_3, yamasaki-san, God2 >
< MySQL_4, sakai-san, GIS >
< ansible_1, yokochi-san, TEKUNABE >
< ansible_2, mofumofu-san, NANACHI >
< ansible_3, tetematsu-san, TENKO >
< ansible_4, zaki-san, OpenShiftMaster >
< ansible_5, yascaim-san, NWmaster >
< ansible_6, ippandansei-san, Climbing >
< ansible_7, nakamura-san, ansible-BOSS >
16 rows found.
Execution time (SQLExecute + Fetch Loop) = 0.000616 seconds.
Command>

TimesTenには一切データ投入していませんが、ちゃんとみれるのがお分かりいただけますでしょうか。

性能結果

あまり良い例を作れなかったのですが…例えば、OracleDBで4秒かかるcountSQLがあります。

ORACLE@oracledb1> select count(*) from TEST_TABLE;

  COUNT(*)
----------
   1655342

経過: 00:00:04.95

これを、TimesTenで実行すると…?

Command> select count(*) from ORACLE.TEST_TABLE;
< 1655342 >
1 row found.
Execution time (SQLExecute + Fetch Loop) = 0.041723 seconds.

0.04秒だよ⸜( ´ ꒳ ` )⸝ 早いね!

あとがき

  • 早い!と思って頂けたら私としてはモウマンタイです。
  • 実は環境構築をMac Dockerでやっていたのですが、OracleDBのコンテナでつまづいたので間に合いませんでした…そもそも前提として、dockerに対する勉強/経験値が足りなかったのですが、今回色々勉強になったなと(特にNW Seg同じにするの忘れてて大変痛い目にあった)思いました。これもいい経験。環境構築記事は半分できてるので、いつかUPしたいな。
  • 明日は gowatana さんの記事!楽しみ⸜(๑’ᵕ’๑)⸝