Twitterのテーブルは3つで構成されているかも(DB入門編)
Twitter, Web, デザイン, 日記 2月 14th, 2010
何気なく、風呂に入りながら「Twitterっていくつのテーブルで構成されているんだろう」と思ってしまって、DBの構造を推測してみた。仕事ではSalesforceのテーブル管理をしたことがあるが、ヤツはとんでもないテーブル数を持っていて、どこに何が格納されているのかさっぱり予測できない。当然カンペキに正規化されているんだろうけれども、あれだけ複雑なアプリケーションであるのと、やっぱりクライアントごとにしっかりデータを分けなければならないというポリシーがあるはずだから(営業データだからね・・)、基本的にはテーブル単位、あるいはDB単位で分けているんだと思う。
で、Twitter。「無料のつぶやきサービス」というサービスで、先のSalesforceとは求められるSLAがまったく異なる。個人単位でデータをエクスポート/インポートすることもない。爆発的に増加するユーザや爆発的に発生するつぶやきに、いかにスケーラブルに対応するかが、このサービスのポイント。それらのポイントをクリアするためには、どのようなテーブル構成が求められるのだろうか。元DBエンジニアの端くれとして、風呂の中で考えてみたのでメモしておきます。現役のエンジニアさんにとってはレベルの低い話なのでスルーしていただければ。
まず基本要件が、大きく3つ。
自分のつぶやきと自分のフォローしているアカウントのつぶやきをタイムラインで抽出できる
自分がフォローしているアカウントの一覧を抽出できる
自分をフォローしているアカウントの一覧を抽出できる
これがTwitterの基本機能(のはず)。そうすると、Salesforce的な設計であれば、
①アカウント一覧テーブル(全ユーザのアカウントを管理。アカウントID、パスワード、アイコン、各種プロファイル)
②つぶやき一覧テーブル(日付、つぶやき内容、つぶやきID)
③フォロー一覧テーブル(登録日付、アカウントID)
④被フォロー一覧テーブル(登録日付、アカウントID)
となるが、この設計だと①を除いた②③④は、アカウントごとにテーブルを用意する必要がある。ユーザーには利用頻度に違いがあるので、一度アカウントを作ったけれどもまったく利用していないユーザーに対してもこれらのテーブルを用意しておかなければならない。論理的に確保しておくだけなのでユーザーが少ないうちは気にする必要はないかもしれないが、その数が数千、数万を超えるようだと無視できないサイズになる。DBの中ではテーブルを作成すると、レコードが入っていようがいまいが、一定の領域を確保してしまうからだ(表領域と言います)。
ちなみに、下はTwitterのアカウント登録数推移。毎日20万~30万人のユーザーが新規登録している。恐ろしい規模だ。この規模で上のような設計をしていたら、ストレージがいくらあっても足りない。

ではそれぞれの共有できるテーブルにしていくには。①は共通のテーブルだからいいとして、②は全ユーザーで共有できそうだ。カラムの構成を
②つぶやき一覧テーブル(日付、つぶやき内容、つぶやきID)
から
②つぶやき一覧テーブル(日付、つぶやき内容、つぶやきID、アカウントID)
とする。こうすれば②も共有できる。自分だけのつぶやき一覧は、SQLで条件指定(where ユーザーID=xxx order by 日付)
で抽出することができる。何億ユーザになっても、テーブルは1つで済む。
しかし、③と④がまだユーザー単位に必要だ。というわけで次に③と④をやっつけていく。
結論から言うと、③と④は合体して、1つのテーブルで管理できる。難しく考える必要はなくて、
③フォロー一覧テーブル(登録日付、アカウントID、)
④被フォロー一覧テーブル(登録日付、アカウントID)
から、
③+④フォロー関係一覧テーブル(登録日付、フォロー元ID、フォロー先ID)
するだけ。錆付いた頭では、頭の中だけで考えるとちょっと時間がかかりました・・・。紙に書けば一瞬だった。こうすると、各レコードは
AさんがBさんをフォローした場合、(”201002132342″,”A”,”B”)というレコードが、
BさんがCさんをフォローした場合、(”201002132348″,”B”,”C”)というレコードが作成される。
こうすることで、すべてのフォロー関係を1テーブルで管理することができるようになる。自分が誰をフォローしているのかを知りたければこのテーブルから(where フォロー元ID=A)で3列目を抽出すればよいし、自分をフォローしてくれているアカウントを抽出するには(where フォロー先ID=B)で2列目を抽出すればよい。
これらの3テーブル
①アカウント一覧テーブル(全ユーザのアカウントを管理。アカウントID、パスワード、アイコン、各種プロファイル)
②つぶやき一覧テーブル(日付、つぶやき内容、つぶやきID、アカウントID)
③+④フォロー関係一覧テーブル(登録日付、フォロー元ID、フォロー先ID)
で、ユーザーごとにテーブルを作成することなく、スケーラブルな対応ができるようになるわけだ(たぶん)。
厳密には、運用上無限に肥大化し続けるテーブルは扱いづらいため、つぶやき一覧テーブルなんかはレコード数単位で分割されていると思う。アカウントを発行するときにでも、①のアカウント一覧テーブルのカラムに、書き込み先のつぶやき一覧テーブルの識別番号を与えているかもしれない。またはテーブル自体は仮想的に一意の名前にして、実際にはIDのレンジでテーブルをパーティショニングしているかもしれない。あと、リストの管理とかもあるし、当然これだけでは済まないのは理解しています。
というわけで、勝手にTwitterのテーブル構造を予想してみましたが、これはTwitterがOracleやMySQLのようなリレーショナルデータベースを使っていたら、の話。GoogleのBigTableのような別のアーキテクチャを使っていたら、これらは全然違うだろうし、BigTableを理解していないので推測もできません。ただAPIを使ってTwitterアプリを作ってみたら、いちいち予想しなくてもわかりそうな気もする。作ったことないし、作る予定もないので永遠に推測の域を出ませんが。誰か正解知ってるのかな。
たまにはDBマガジンでも読んでみるかな。トレンドはキャッチアップしておかないとね、モチベーションがあるうちに。
![]() |
Google App Engine for Java [実践]クラウドシステム構築 (WEB+DB PRESS plus) (WEB+DB PRESSプラスシリーズ) (WEB+DB PRESS plusシリーズ) 技術評論社 2009-09-10 |
関連記事
- 久しぶりに書評でも|村上式シンプル英語勉強法
- 家計簿をつくろうと思います
- 2月の読書
- Wordpressのパフォーマンス向上まとめ
- 最近の読書|Twitter Power
- Ogilvy Japan Blogger Gatheringに参加してきました
- 4月の読書

![Google App Engine for Java [実践]クラウドシステム構築 (WEB+DB PRESS plus) (WEB+DB PRESSプラスシリーズ) (WEB+DB PRESS plusシリーズ)](http://images-jp.amazon.com/images/P/4774139858.09.MZZZZZZZ.jpg)
