レベル1分散でも DB で JOIN させる方法

by tanabe on January 26, 2009

いわゆる mixi のレベル1分散というものがあって、「join は使わない(方がいいケースもある)」というような話も出てきたりするんですが、join で解決できる問題はアプリケーションコード書くよりも DB にやらせたかったりします。

一方でそれぞれのテーブルは別の DB 上に載っているので、ふつうに join するわけにはいきません。

てことで、無理やり join しようとやってみた手。

まず、db_a に載っている table_a の必要なレコードを取得します。

んで、そいつの1レコードにつき一つの select 句をアプリケーションで生成します。

select
  v1 as name1
, v2 as name2
, v3 as name3
, v4 as name4 

そしてできあがった select 句を union all.

ポータブルな即席 view のできあがり。

このできあがったものを一つのテーブルとみなして join の対象とし db_b に載っている table_b, ... たちとのクエリを生成します。

これで二つの DB にまたがった似非 join が使えます。アプリケーションで妙なループを連発してコードの可読性を下げるよりもマシに使えるような気がするんですが、どうでしょうか?

発行される SQL クエリのイメージはこんなかんじ。(実際はアプリケーションの中でもう少し見通しがよいようにまとめたり整理したりしますが。)

select
  *
from
  (select v1 as name1, v2 as name2, v3 as name3, v4 as name4
  union all
  select v5 as name1, v6 as name2, v7 as name3, v8 as name4
  union all
  select v9 as name1, v10 as name2, v11 as name3, v12 as name4
  union all
   ...
  ) t1
  join
  table_b t2
    on (t1.name1 = t2.name1)
  join
  table_c
    on (t1.name3 = t3.name3)
where
  ...

もちろん、uninon all で作ったほうは index も何もあったもんではないので、そちらはそれなりにレコード数が限られていないと使い物にならないと思います。

案外パフォーマンスもまともに出る(インラインで作ってる区分テーブルみたいなもんなんで)ので、下手なアプリケーション join よりも使えるんじゃないかなーなどと思ってたりします。