UD Day 22 DB仕様1 Cassandraの構造

Cassandra(及び同じ仕様に基づくScyllaDB)のテーブル構造は、通常のRDBと異なります。データが複数のノードに分散することを前提とした構造となっているためです。複数のノードにまたがるクエリーを実行する必要がある分散DBにおいては、結合のように、通常のRDBと同じクエリーをそのまま行おうとすると、ノード間を行ったり来たりする事態が発生し、過剰にオーバーヘッドが生じることになります。このような状態を回避するために、基本的にはRDBで言うPrimary Key的なものでクエリーを行うことになります。その結果として、クエリーから設計し、クエリーに応じたテーブル設計を行うという順番の設計になります。
以降では、Cassandraのデータ構造を見てみます。

クラスター、キースペース、テーブルの関係性

上記の図は、Cassandraの全体の構造を表します。それぞれの構成要素は、複数のノードにまたがっています。Clusterはシステム全体(Keyspace、Tableが属する全体の論理的な単位だと思えば良いと思います)、KeyspaceはRDBでいうDBの単位、Tableがテーブルと捉えると的確だと思います。

テーブル構造

それでは、テーブルの中の構造はどうなっているかと言うと、上記のようになっています。

RDBでいうPrimary Keyは、Composite Keyと呼ばれ、これは、Partition KeyとオプションであるClustering column(key)で構成されます。
また、static columnというpartition keyに対して紐づくデータを持つこともできます(Partition Keyに直接紐づく情報)。
データの分散(ノードへの分散)は、Partition keyによって行われます(*)。Partitionの中で特定の値にアクセスする場合に、さらに、Clustering Keyを指定する、という形で動きます。
(*)…Partition Keyのハッシュ値を計算し、その値に応じて、実際のノードを決めています(Cassandraのシステム内)。逆に言えば、Partition KeyをWHERE句に指定すれば、対象のノードだけを読みに行く、ということになります。

補足)RDBでいうところの行は、Clustering Keyのすぐ外の四角と同じであると考えられます。これらの行のいくつかをグループとしてまとめて、それに対してIDをふって、グループ単位でのアクセスをしやすくしているのがPartition Keyの含まれる四角と考えるとわかりやすいと思います。Partion Keyのすぐ外の四角を”Wide Row”と呼びますが、この名前もこの考えから、通常のRowとは異なるという意味の呼称と推測できます。ただし、これは、データをwide modelで作った場合であり、RDB的なものにもできます(skinny model と呼ばれます)。
Partition Key、Clustering Keyの例)UDの場合、ウェブページに対してコメント(複数も可)が記載されるシステムなので、Partition KeyはURL(もしくはURLを加工したID)、Clustering Key各コメントが持つコメントIDが該当します。

以上、Cassandraのデータモデルの説明でした。この構造を踏まえて、クエリーの定義、テーブルの定義を行っていくことになります。(続く)

UD Day 21 機能外要件

運用・保守要件などの機能外要件として何があるか、それぞれどのような考えをしたかについて述べます。

  1. 運用・保守要件
運用・保守においてありえる作業

以下は実際の要件定義書からの抜粋です。

(1) SW保守 

6〜10年程度のライフサイクルを想定する。    
利用するコンポーネントに応じて異なるが、GCEの場合にはOSアップ、GCSの場合にはMWアップ、GAEの場合にはアプリに対して、問題の検知と解決のための保守を実施する。
問題の経路としては主に以下を想定する
・ アプリケーション起因のバグ
・ ユーザーからのインシデント報告
・ 監視によって検知したエラー
別途PM計画書で規定する課題管理プロセスに従って、起票(検知)〜クローズまでを実施する。(問題 => 課題 => Action *)
*) 問題(インシデント:単なる事象)の検知 => 問題の分析により課題を浮かび上がらせる => 課題の解決のためのアクションを設定するの流れ。

(2) バックアップ

バックアップ
(3) サービスデスク    
アプリの設定項目より、ユーザーが改善、要望、クレームを送ることができる機能を設定し、運用者が通知を受けれるようにする。(もしくはメールで送信されるような形)
(4) IT運用    
自動化できない作業をオペレーション運用作業として特定して、運用上の実施項目として定義する。現時点で明示的に必要なものを以下に記載する。
・ 不正ユーザー報告があった場合には、対象ユーザーを利用不可とするなどのことを実施する
・ バッチの再実行などの手動対応
・ パターン化された特定障害に対しての手動対応
(・ バックアップ、ログファイル退避などの作業は自動化、オペレーション対応は不要)
(5) 資産管理    
SW資産を購入する場合には、年次で棚卸を実施する。

尚、計画停止については、初期の段階では月次を想定し、お知らせやコメントの吹き出し形式などで計画停止の通知をすることを想定しました。

2. キャパシティ・パフォーマンス要件

 a. キャパシティ要件
  UD Day 20のような形でキャパシティを想定
 b. キャパシティ拡張基準
  スケールアップ、スケールアウトについての基準を策定する。
  ・ スケールアップ
    トランザクション量の増加に伴って、スケールアップをまず行うこととする。
    別途記載のリソース監視時の規定容量に基づいて、超過時にインスタンスタイプの変更を行う。
  ・ スケールアウト
    スケールアップによる限界もしくはスケールアウトによるコストメリットが確認できる場合には、スケールアウトを行う。
    Web/APについては、Auto Scalingの設定を行い、自動拡張の設定を行う。
    DBについては、データのDB分割(Sharding。データを異なるDBに保存する)を行う事によるスケールアウトを検討する。
 c. パフォーマンス要件
  ・読み込み時にかかる時間
  ・書き込み時にかかる時間

3. リリース方法
要件定義では詳細化はせず、GithubもしくはGitlabを用いるということだけを決めました。実際にどのようにやるかは構成が決まり次第、ものを作る中で簡単にできるためです。

4. 監視
GCP及びそのツールでモニタリングが可能なもののうちどれを採用するかという判断を行いました。最終的には、ツールとしてはStackdriverのLogging/Monitoringを採用しています。

他にもNWのセキュリティやデータの暗号化について検討しました。これらについての詳細への言及はここでは控えます。(続く)

UD Day 20 オペレーショナル・モデル(RD)

オペレーショナルモデルでは、必要となるノードと各ノードにおける要件を論理(概念上必要となる単位でのまとめ)と物理(実際の配置のされ方)でまとめます。アーキテクチャの選定で、候補となりそうなプロダクトがわかってきているので、実際にオペレーショナルモデルに当てはめてみて、全体感がどのようになるかを掴みます。同時に、利用者数の規模をベースとしたスペック案についても考えてみます。
まず、大まかな対象(登場するシステム)ですが、以下のものになります(当然ですね)。

登場するシステム

1つ目の構成は一般的なウェブシステムの構成で、DBのプロダクトとしてMySQLを採用したものです。ノードは、左からLoad Balancer、Web、Application、Database(及びDatabaseの副ノード)、そして下段左が管理用ノードになります。それぞれの台数については、ここでは考慮に入れず、単純に役割別で登場し得るノードを記しています。基本は各ノードは単機能ですが、管理ノードについては、構成、監視を共存させています。これは、初期のコストを押さえるためのアイデアであり、分割することも当然考えられます。

web-ap-db(mysql)の標準的な構成

上記の構成に対して、ユーザー数の規模ごとにどのようなコストになり得るかを考えたものが、次の表です。ここでは、Case.0〜3までを記載していますが、4以降にも実際には続きます。各Caseで想定するGCPのノードタイプ、そして他に必要なもの(NWコスト、監視、ノード以外のストレージなど)の項目も用意しています。
Case0から右に行くに従って、ユーザー数が多い想定です。実際にはユーザー数がいくらくらいまで考えられるかも検討することもできますが、クラウドを利用するメリットはスケールアップ・アウトが容易である点を考慮すると、具体的な細かいユーザー数を事前検討することには実益はないと判断して省いています。ですので、これはあくまでもおおよそのイメージと捉えられます。
その上で、右に行くに従い、ノードの種類がよりハイスペック、ノード数がより多くなります。
セル背景色が緑、青の行は、それぞれMySQLの代わりにBigTableを用いる場合のコストとそれを含めた全体コストになります。Big Tableは製品としての魅力が非常に高い(分散性、レイテンシーの観点で優れている)ものですが、コストで比較した場合にはGCE&MySQLの構成の方が優れていることになります。(同じような理由から、GAEを採用していません。基本的な法則として、サービス対象が上位のレイヤーを含むほどコストも高くなるようです。)

ユーザー数規模に応じた構成例

基本的な考えは以上となりますが、要件定義の段階で考えた他のオペレーショナルモデルの例もここに付記します。

Web+App、redis、HBase

1つ目は、DBにredis+HBaseを採用した場合の構成です。分散性とレイテンシーを考えると良い構成だと思いますが、ノード数が多くなる欠点があり、採用していません。

GKE、Cassandra

2つ目は、ウェブ系と管理系にGKE、DBにCassandraを使った構成です。GKEは、全体のノードプールの中に複数の仮想ノードがあるというイメージです。リソースを十分に使うという観点で望ましいと思いましたが、DBに対しては適用し難く、結果として、GKEとGCEという2つの運用が存在することになるのが嫌だったので、採用しませんでした。

これ以外にもいくつかのパターンを考え、最終的な構成を決定しました。その構成は後の章で登場する予定です。(続く)

UD Day 19 ブラウザ仕様検討項目

UDはブラウザなので、ブラウザとしての機能として何を保持するべきかを検討する必要があります。ブラウザの機能的な要件については、詳細な文書としてはまとめていません(ある程度標準化されている領域のためです)が、何が必要かだけはまとめておく必要があります。

UDで必要と考えたもの(標準機能および設定項目)については、以下のものです。

標準機能の一覧
設定項目の一覧

上記を中心として、設計、実装フェーズでさらなる詳細化をしました。(続く)

UD Day 18 アーキテクチャーの検討13(その他の基盤的な検討事項:主にCassandra)

アーキテクチャーの検討としては、前回12までの分で全て(要件定義フェーズ)ですが、以下にその他諸々で調査した内容について記載します(走り書きの類です)。以上です(続く)

・GKEはDocker?実績はどうか?
 GKE はdockerベース。実環境で確認済み。web/ap層は冗長化で可用性は確保できると判断。実績はまあまあ(心配する声があるのも事実)。Data層は??
 k8sのData層としての利用は否定的な見解(Netflix)

・Cassandraで暗号化はできるか
 商用以外は見つからない。アプリ側でSensitive Dataのみ暗号化する
 (例えば、暗号化方式を複数持ちデータのはじめ1文字(数bit)で暗号化方式を指定する(一見するとどう暗号化してるのかわからない)

・CassandraはインメモリーDB(redis, memcachedなど)と併用しなくていいのか
 Netflixのテックblogに詳細なレポートあり。結論的には、SSDベース  Cassandraがあれば、インメモリーDBなしにできる(AWSの例だが、GCPの方が、SSDはパフォーマンスが良い印象がある。別記事にて)。
 レポートの結論としてはより少ないSSDベースのノードで置き換えれる(コスト安くなる)かつlatencyがより少なくなるとしている。
  

・CassandraなどのDBをk8sのStatefulSetで運用するのは問題あるか
k8s on 2 GCE nodes vs 3 GCE nodes
Defenitive Guideでは、Dockerの利用は非推奨。(Dockerでパフォーマンス上問題となり得るのがネットワークとデータディレクトリーでソフトウェアルーティングが用いられている点。Cassandraの場合、50%程度の低減となりえる)

 ・(関連)DockerとVMのパフォーマンス比較をするとどうなるか
  DockerはNativeよりやや劣る程度という記載 
  CPU, NW, IOの単位で計測結果を記載。P21の理論値はローカル内だから気にしなくて良いかと思う。Port-forwardingかdedicated IPのどちらかは気にした方が良さそう。(GKEの場合は?Docker-to-docker(orVM)をテストした方が良いかも。)

・Cassandraをmulti-DCでdeploy可能か
 可能だが、Readのlatencyについて懸念あり。実環境で2ケースを試すべき(Single-AZ and multi-AZ:前者同じAZに3つ、後者2-3つのAZに6つ )。
 latencyはAZ(zone)間のNWパフォーマンスに依存。Multi-AZ構成にする場合の考察はこの記事が参考になる。
 一つの構成例:3つのAZ、各AZに2つのノード。RF=3として、AZ1〜3のそれぞれに同じレコードがある。一つのAZが死んでも大丈夫。
 NW帯域は別ゾーン(同一リージョン)は、同一ゾーン内でどう異なるか(以下のリンクより)同一Zone: 2Gbps/コア別Zone: 1.5〜2Gbps/インスタンスとなりそう。
 方針:上記の2ケース(同一ゾーンor同一リージョン異なるゾーン)をデータを入れた状態で試し、レイテンシーがどのくらい異なるかを実際に確認するのが良さそう。
      同一ゾーンしか選択肢としてないとなった場合には、アウテージの際のユーザ通知を考える形とすべき。
  GCPのblogによれば、2Gbps/コア、max 16Gbps/インスタンスみたい。
  Netflixでは、multi-regionのCassandraを運用してるみたい。
  ちなみにEC2の計測結果は以下(同一zone内)。最新だとでかいやつはmax25Gbps。
  2014のデータだが、計測結果(AZ間もある)がある。AZ間はAZ内より落ちる(程度はAWS, GCPで異なる)
 => Multi-AZは最小で3つのAZ、各AZに1つづ、RF=3であるが、このケースでは単に冗長性を持っているだけで、まだ分散DBの意味は持たない。増やすにはAZあたり3つづつとなる。
   また、Multi-AZの場合、AZを2つとするのには意味がない(Quorumが失敗する)。そう考えると、AZ=3が正しい。以上から、初期の段階では、マルチAZの構成は取らないものとする。

Cassandraの冗長性: replication-factorの設定値次第:node=3なら3、node=4以上なら、3〜ノード数以下という推奨例

・Cassandraの場合のテーブル設計
 RDBと異なり、クエリー毎にテーブルを作成するという方針でテーブル設計をするのが一般的(Datastax社ガイド)
  「データがCassandraに格納される順序がデータの取得のしやすさと速度に大きく影響する場合がある」(amebaのtech blogはこれでいうとダメな例かもしれない)
 運用後にデータが特定のノードに偏るなどの事象が発生(設計時に分散を考慮してやるべきだと思うが・・・)
 Cassandraのデータモデルは、KeySpace(Database)-ColumnFamily(Table)-Key(PrimaryKey??)-SuperColumn(data)-Column(data) となっている。
 Cassandraでの実際の設計例を記載(2009年に書かれたものなので少し昔なのが気になるが)
 英書を読むのが一番よさそう。

・Cassandraの実運用における問題点は?
 排他制御、削除周りの難しさが記載されている。この点は現バージョンでの詳細な調査が必要かも。あと、テスト。
 クラスタあたりのノード数の限界(1000程度)、ノードあたりの容量(3.xなら1TB程度)などの有用情報、一貫性問題についての言及


技術関連のリンク)
FBで使われている技術(かなり網羅的)
FBで使っている技術(2011年の資料だが参考になる)。HayStackで画像の管理をしている(保存・取り出し)のは参考にすべきかもしれない。初めはBlobで作って、どっかでHayStackに移行するとか。
画像関連。 回答が秀逸。Generalなやり方や考え方に言及している。RDBだとボトルネックにもなりえるし、BLOBを扱うのは微妙かもしれない。
FB Haystack使用
Swift -> S3に画像を保存する。
MySQLの分散。Group Replicationがやりたいことを満たすソリューション。Master、Read replicaでも良いが、当初考えてたテーブル分割は意味が低減するか?
上のblogに記載のMySQLの分散方法まとめ。正直、テーブル分割(分散DB的)を想定した場合に使えるものはないかも。
MySQLのCharacter set(encoding)。選択肢としては、cp932(日本語)が良さそう。
GCEでSSDを使う(やり方の参考にとてもなるので、実装時に見るべき!)

UD Day 17 アーキテクチャーの検討12(Authを考慮したアプリサーバー構成)

仮に認証方式としてJWTを採用する場合のアプリサーバーの構成がどのようになるか?について、考察してみたいと思います。

JWTには、有効期限の短いaccess tokenと有効期限の長いrefresh tokenの2つを用いるというやり方があります。
クライアントは、初回ログインで認証を行うサーバーから上記二つを得て、以降のやり取りでは、必ずaccess tokenをつけて、トランザクション処理を行います。
access tokenが期限切れとなったら、refresh tokenを使って、認証サーバーからaccess tokenを発行してもらい、以降のやり取りではこれをつけて、トランザクション処理を行います。refresh tokenと有効期限の情報は、DBに保存します。Refresh tokenがJWTの形式の場合、exp(有効期限)をtokenの2つ目のClaim内に含むので、tokenのみを保存すれば良いということになります。
実際のログイン時のHandshake(クライアント・サーバー間の処理の流れ)は別記事にて記載予定ですが、上記を踏まえると、サーバーの機能としては認証を行うものとそれ以外の処理を行うものの2つに分けることができそうです。つまり、以下のような構成になります。

サーバー構成と利用するTokenの種類

上記の構成でAuth ServerとResource Serverがそれぞれ認証サーバー、それ以外の処理用のサーバーとなりますが、これらの役割を共有にするという考え方もできます。しかしながら、トークンの生成・解読の際に利用する秘密鍵の漏洩に対するリスクを最小化する場合には、共有よりも役割を分けることが望ましいと考えました。その結果として、上記の構成を採用しています。(続く)

参考リンク)
JWTの実装方法についての質問

UD Day 16 アーキテクチャーの検討11(Auth)

認証と認可について、どのように行うかを考える場合、StatefulとStatelessの2つのどちらを採用するかを検討する必要があります。それぞれの特徴をまず見ていきます。

Stateful
 いわゆるウェブのセッション管理。
 タイムアウトは10分〜2時間が一般的。
Stateless
 JWT(JSON Web Token: RFC7519)というJSONのオブジェクトにセッション情報を保持し、サーバーでの保管が不要。
 JWTのtokenは、.(ドット)で3つに区切られた文字列(1つ)である。
 3つのセクションは、ヘッダー(アルゴリズムとJWTのタイプ)、Payload(ユーザー情報、メタデータ)、電子署名(左記2つとsecret(鍵)から作成)である。
 JWTで利用するライブラリーは脆弱性がないことを確認する必要がある。
 アルゴリズムがnoneの場合の脆弱性があるので、noneのものは一律failさせるべきである。
 secretはissuerとconsumerだけで保持し、外には出さない。
 sensitiveデータをJWTの中に含めない。含める場合には、JWEを利用する。
 replay attackに対する対策として、jti claim(nonce: ワンタイムパスワード)の利用、有効期限、作成日時の情報を含める。
 詳細は、OWASPのガイドラインなどを確認する。

OWASPでは、Statelessが徐々に増えており、脆弱性をクリアすれば、良い方法と記載されています。しかしながら、JWTを非推奨としているポストも多くあり、Statelessの採用を考えがたくしています。

まとめると、Statefulは、取り得るオプションですが、各トランザクションの頭にsession-idの確認があり、このreadがオーバーヘッドとして常に加算されます。また、セッションの時間が短いのもユーザービリティの観点で問題となり得る可能性があります。Statelessについては、最もメジャーなのは、JWTですが、色々と指摘されている問題があります。Webアプリの前提か、nativeアプリの前提かでも異なるので、これらの点を踏まえて決める必要があります。

ちなみに上記リンクで考慮すべきとしているポイントは以下のものになります。これらの観点で自分のアプリがどうなるかを考慮した上で、最終的な方式を決定しました。
 (1) They take up more space(サイズが小さくない)
 (2) They are less secure(セキュアではない)
 (3) You cannot invalidate individual JWT tokens(サーバー側で無効化できない)
 (4) Data goes stale(データが古くなる)
 (5) Implementations are less battle-tested or non-existent(長い期間の試行を経ていない)

仮にJWTを採用する場合どのようなサーバー構成にすべきでしょうか。また、一連のやり取りはどのようになるでしょうか。次はそれについて言及します。(続く)

UD Day 15 アーキテクチャーの検討10(NW速度を測る)

最終的なデプロイメントモデルを検討する際の一つの材料とするためにNWの速度を測ります。具体的には、GCPのとあるリージョン内の同一Zoneもしくは異なるZoneのそれぞれのケースでNW速度の実測がどの程度異なるかを測ります。

前提: n1-standard-4 (4コアのもの)。OSはgcloud computeコマンドで作成されるデフォルトOS(Debian-9)を利用。同一内の場合、asia-northeast1-aを利用、異なるZone内で同1-aおよび同1-bを利用。
試行内容: 各ケースにおいて、サーバー側、クライアント側に分け、それぞれiperf3コマンドを実行する。

同一Zone内、異なるZone内での測定結果

Zoneをまたぐ場合に、約24%程度の劣化があることがわかります。このことは、DBサーバーとしてCassandra(ScyllaDB)を採用したことによって、重要となります。特にfull repairと呼ばれるノード間の整合性を修正するジョブを行う際に、非常に多くのI/O、NWトラフィックが発生するため、これをいかに早く終わらせるかという観点でNWのパフォーマンスが重要になります。
DBノードをマルチゾーンとする場合の性能劣化24%であり、これは少なくない数字なので、同一ゾーン内を選択しました。
以下は、実際の計測ログです。(続く)

同一Zone内の施行(サーバー)
同一Zone内の試行(クライアント)
異なるZone間の試行(サーバー)
異なるZone間の試行(クライアント)

UD Day 14 アーキテクチャーの検討9(Web Framework)

選択肢が多いと人はむしろ選べなくなる(選択のパラドックス)

ウェブのフレームワークを選定しようとすると、まさにこういう状況に陥ります。フレームワークが言語ごとにあり、各言語内でも多くの選択肢があったりします。ありがたいことかもしれませんが、何かしらの指標で選択する必要があります。

UDでは、スケーラブル、かつ、コストパフォーマンスの高いプロダクトを採用しようというのが、サーバーサイドのシステムに求めた共通の要件です。APIサーバーのアプリケーションを作る場合には、まずは、言語、次にフレームワークの選定が必要となります。

言語に関しては、GOを選択しました。パフォーマンスの観点で良いためです。C++の採用も考えましたが、その当時はウェブフレームワークで良いものが見つからず、GOにしました。上記のリンクによれば、大凡Javaに匹敵するレベル、C++よりは少し劣るという立ち位置にあると考えられます。

GOの中でもフレームワークは多数ありますが、これまで述べたパフォーマンスに加えて、成熟度、Githubのスター数などから比較し、gin gonicを選択しました。ベンチマークの一例としてこちらのサイトがあります。当時と結果は変わっていると思います。(続く)
参考リンク)
なぜ私達はPythonからGoに移行したのか

UD Day 13 アーキテクチャーの検討8(データサイズの極小化)

データを極小化するためには、データの圧縮保存が必要となります。どういったアルゴリズムの選択が望ましいかについて考察します。

圧縮方法としては、以下のものが考えられそうです。
1. base64(数字、アルファベット、+-=の64文字)への変換
2. バイナリーコードへの変換8bit, 16bitなどのエンコード
3. 数字圧縮アルゴリズム(VB Code, γCode …etc)の利用。主に小さい値が多くあるような偏りのあるケースで有効そうです
併せて、DBのの圧縮モードを利用可能である場合はそれを利用するなども検討する対象になります。

圧縮を検討する対象としては、以下のaからcのものが考えられます。

a. ハッシュ値
ハッシュ値は、視覚的には、0から9の数字とaからfの文字で表現されます。上記の方法のうち、1、2の適用が考えられます。ここでは、MySQLの利用を前提とした場合にどのようなサイズの差が生じるかを見たいと思います。base64については、文字列長が固定的にならないため、比較対象からは外しました。つまり、0からfの文字列(hex(0-f))、およびバイナリー(binary, USC2)の間で比較しました。
 ー hex(0-f):varchar(32)、lanti1(1byte code)で定義
 ー binary:binary(16)、unhex(16進数) でバイナリー文字列に変換して、返す(バイナリー文字の1文字は16進数のペア)
 ー USC2:varchar(8)、USC2(2byte code)で定義

ハッシュ値の圧縮

結果は上記の通りとなり、それぞれ93M、69M、73Mとある箇所が、DBの圧縮モード不使用の場合のサイズ、それぞれ49Mとある箇所がDBの圧縮モード利用の場合のサイズとなります。
非圧縮の場合は、binaryが一番優れており、圧縮モードを利用した場合はいずれも変わらない事がわかります。
利用するDB製品によっても異なると思いますが、非圧縮の場合には、binary変換の上で保存するのが望ましいとの見解を得ています。

b. INTの圧縮
INT型には複数の種類があるので、INT型のうちどれが適切かを正しく設定する必要があります。最大値を鑑みて、小さい型にするのがサイズの観点からは望ましいです。
INT等の大きい値を含む型については、数値圧縮アルゴリズムを実装することも検討が必要です(アプリ側)。UDでは、INTの圧縮は特に行っていないので、ここについては、方針のみ考えました。

c. VARCHAR
VARCHAR(m)とした場合のmはバイト数ではなく、文字数になります。
コメント文の場合、モバイル端末では280byte以下までの入力を仕様としています。
この場合、280byteの制限をこの時点でしているため、VARCHAR(280)とすれば良いことになります。

d. テーブルの圧縮 (ROW_FORMAT = COMPRESSED)
読み取りの頻度が多い、SSDを利用する等のケースで特に有効なようです。圧縮によって、ディスク〜メモリー間の転送量、ディスク、メモリーにおける使用量が少なくなります。
圧縮領域と非圧縮領域は最大で1:1程度の比率、低い場合で9:1程度になります。圧縮は少なくとも50%以下なので、メモリ利用の観点では、圧縮の利用が望ましいようです。変更が少しでもあるたびに該当のブロック全体を再圧縮・ディスク書き込みとなるので、書き込み頻度が多いケースでは利用に向かないとされています。
上記は、MySQLの主要なDBエンジンであるInnoDBの場合ですが、Facebookが書き込み性能・圧縮成功率を更に高めたエンジンMyRocksというプロダクトがあります。今回のユースケースは書き込みそれなりに多いことが考えられるので、MyRocksの採用もありかなと考えていました。結果的には、Cassandra系なので、この部分は無駄になりましたが…(続く)

参考リンク)
InnoDB Pluginことはじめ
データ型のストレージ要件
DBでバイナリー型にSELECT実行
MyRocks