CBA Google App Engine 20101208

2,045 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,045
On SlideShare
0
From Embeds
0
Number of Embeds
26
Actions
Shares
0
Downloads
17
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

CBA Google App Engine 20101208

  1. 1. Googleを支えるクラウド技術 <br />スティルハウス 佐藤一憲<br />
  2. 2. アジェンダ<br />Google App Engineとは<br />分散KVSとBigtable <br />Datastoreサービス<br />Datastoreのクエリ<br />
  3. 3. 自己紹介<br />スティルハウス 佐藤一憲<br />twitter: @kazunori_279<br />ブログ: 「スティルハウスの書庫」<br />Web: http://www.sth.co.jp/<br />コミュニティ活動<br />appengine ja night<br />Google API Expert (App Engine)<br />主な業務<br />開発: Adobe Flex/AIR、Rails、GAE/J<br />テクニカルライティングや翻訳(ペンネーム吉川和巳)<br />セミナー講師など<br />
  4. 4. Google App Engineとは<br />
  5. 5. Google App Engineとは<br />Google App Engineとは<br />Webアプリホスティングサービス<br />自分のアプリをGoogleのクラウド上で運用できる<br />2008年4月にPython版リリース<br />2009年4月にJava版リリース<br />
  6. 6. Google App Engineとは<br />利用状況(2010年12月現在)<br />10億PV/日(mixiと同程度)<br />開発者の増加は10万人/月<br />アプリの増加は15万件/週 <br />
  7. 7. App Engineのすごいところ<br />App Engineのすごいところ<br />「2ケタ安」の圧倒的な低コスト<br />どこまでもスケール+高可用性<br />開発・運用環境が構築不要<br />
  8. 8. 「2ケタ安」の低コスト<br />無償分と有償分<br />初期コストはゼロ<br />無償分だけでも“400万PV/月相当を運用可能”<br />
  9. 9. 「2ケタ安」の低コスト<br />「ふにゃもらけ」の事例<br />MixiアプリをApp Engineで提供<br />1日600万PV以上(月1.8億PV相当)<br />Googleからの請求は1日$15(月額4万相当)<br />スティルハウス担当事例<br />従来はデータセンターのサーバーを1台使用<br />400万件のデータ(約11GB)をApp Engine移行<br />月額$4<br />サーバー管理者が不要に<br />
  10. 10. どこまでもスケール+高可用性<br />Googleのクラスタ環境を簡単に利用できる <br />自動クラスタリングによる負荷分散と高可用性<br />負荷状況に応じてApp Serverを動的に増減 <br />アプリ間の隔離性を維持、個々のアプリの安全性とパフォーマンスを確保<br />Bigtableのスケーラビリティ<br />RDBにつきもののスケーラビリティ上限がない<br />テーブル間の結合(join)ができない<br />トランザクションの整合性保証の範囲を限定している<br />App Engineの全アプリのデータは、1つのBigtableテーブルに格納されている<br />
  11. 11. スケールアウト事例<br />ホワイトハウスの"Open For Questions" <br />2日間だけ提供された投票サイト <br />その結果を受けてオバマ大統領が記者会見を行った <br />10万件の質問と360万件の投票を受け付けた <br />ピーク時には毎秒700回のクエリを実行した <br />App Engineをout of boxで使用<br />Google Moderatorのソースをベースに、ホワイトハウス側の開発者がチューンしてデプロイ。Google側による特別な作り込み等は行っていない <br />App Engine上の他のアプリには一切影響なし<br />
  12. 12. スケールアウト事例<br />"Open For Questions"のトラフィック推移<br />
  13. 13. 開発・運用環境が構築不要<br />統合開発環境を提供 <br />サーバーの構築や管理が不要。デプロイが容易<br />管理コンソールを提供<br />ログ管理、管理コンソールや各種ツールを提供<br />
  14. 14. Google App Engine Stackの構成<br />Google App Engine Stackの構成<br />
  15. 15. App Engine Stackの構成要素<br />App Engineが提供するAPI<br />
  16. 16. App Serverについて<br />App Serverのサンドボックスによる制限<br />HTTPリクエスト処理は最大30秒まで<br />App Engine最大の制約のひとつ<br />時間のかかる処理はTask Queueで<br />ファイルシステムへの書き込み<br />外部サーバへのソケット接続<br />HTTPリクエスト送信は可能<br />スレッド生成<br />ガベージコレクション実行やシステム停止<br />カスタムクラスローダの利用<br />
  17. 17. App Serverのスケールアウト<br />高負荷時の自動デプロイ <br />高負荷状態が一定時間続くと、新しいApp Serverが追加され負荷分散し、負荷が低くなると削除される <br />アプリが受けられる負荷に上限はあるか? <br />同時30リクエストの制限<br />リクエスト処理時間に応じてスループット上限は変化<br />それ以上の負荷を扱いたい場合はGoogleに依頼する。アプリごとにsafety limitを解除できる <br />
  18. 18. 分散KVSとBigtable <br />
  19. 19. 分散KVSとは<br />分散KVSとは<br />「キー」と「値」のペアを保持する分散データストア<br />「Map」や連想配列のようなもの<br />
  20. 20. 分散KVSとは<br />各社のクラウド向け分散KVS<br />Google<br />Bigtable<br />Amazon Web Service<br />Amazon Dynamo<br />マイクロソフトAzure<br />Azure Storage Service<br />楽天「ROMA」<br />オープンソース実装<br />Facebookによる「Cassandra」など<br />
  21. 21. 分散KVSの長所短所<br />メリット<br />スケールアウト構成を取りやすく、スケーラビリティが頭打ちにならない<br />高可用性を実現しやすい<br />デメリット<br />データ全体を対象としたトランザクションの整合性確保が困難<br />RDBのような高度なクエリやテーブルの結合(join)が困難<br />
  22. 22. 分散KVSとRDB<br />分散KVSとRDBの長所短所<br />
  23. 23. RDBはスケールしない?<br />RDBのスケーラビリティ強化手段<br />RDBサーバーのスケールアップ<br />大型サーバーへの載せ替え<br />DBのレプリケーションやシャード(パーティション)分割によるクラスタ構築<br />分散キャッシュ(Oracle RACやmemcachedなど)によるクラスタ構築<br />->いずれも複雑で高コストなソリューション<br />数千万~数億円以上<br />RDBのスケールアウトは原理的に困難<br />
  24. 24. RDBとCAP定理<br />CAP定理<br />UC Berkley大のEric Brewer教授が2000年に発表<br />Consistency, Availability, Partition<br />分散環境(P)では整合性(C)と可用性(A)間でトレードオフ発生<br />
  25. 25. BASEトランザクション<br />BASEトランザクション<br />CAP定理を反映した分散環境での“ゆるい”トランザクション<br />Basically Available<br />可用性の高さを優先する(悲観排他より楽観排他)<br />Soft-State and Eventually Consistent<br />状態の一時的な不整合を許容する<br />結果的に整合性が確保される仕組みにしておく<br />例:DNS、Google WaveのOT<br />
  26. 26. 分散KVSとCAP定理<br />分散KVSでは<br />ACID保証の範囲を制限、可用性を確保<br />
  27. 27. クラウドによる全体最適化<br />分散KVSの「制約」こそ「クラウドのキモ」<br />整合性が限定、結合できない、etc...<br />->アプリが分散環境に対応するための必須条件<br />クラウドによる全体最適化<br />分散環境に対応した多数のアプリを、きわめて効率よく集約(コンソリデーション)できる<br />独立したOS、仮想マシン、DBが不要<br />クラウドという巨大単一コンピュータへの融合<br />「2ケタ安」のコストを実現<br />無制限のスケーラビリティと高可用性を安価に提供<br />メインフレームへの回帰?<br />
  28. 28. クラウドによる全体最適化<br />
  29. 29. Bigtableの概要<br />Bigtableとは<br />巨大分散データストア<br />リレーショナルモデルに基づくRDBではない<br />いわゆる分散Key-value Store(KVS)やNoSQL<br />膨大な数の汎用サーバーをつなげてペタバイト規模のデータを扱えるよう設計<br />現在およそ数PB<br />全世界36か所以上のデータセンターに配置された数万台~数10万台のサーバーに分散<br />Googleクラウドの「虎の子」<br />
  30. 30. Bigtableの概要<br />Bigtableの歴史<br />およそ7人年の開発作業を経て、2005年4月からプロダクション利用を開始 <br />Googleの70以上のプロジェクトが利用 <br />検索, GMail, Analytics, Finance, Earth, YouTube, Mapなど<br />Bigtableの特徴<br />実用上、無制限のスケーラビリティ<br />サーバー冗長化による高可用性<br />
  31. 31. 無制限のスケーラビリティ<br />実用上はスケーラビリティに上限がない<br />テーブルの規模が100件でも、数1000万件でも、個々の行の読み書きは数10 ms程度で完了<br />膨大な数のユーザーがBigtableに同時にアクセスしても、レスポンスの低下は発生しない<br />一般的なWebアプリケーションの大半では、RDBサーバーがボトルネックとなってデータ量やアクセス件数の増加にともないレスポンス時間が低下<br />Bigtableを使ったWebアプリケーションではそれが皆無<br />
  32. 32. サーバー冗長化による高可用性<br />Google独自の分散ファイルシステム「Google File System(GFS)」<br />異なるラックに設置された3台以上のサーバーにコピー<br />サーバー障害によってデータが失われる可能性はきわめて低い<br />いずれか1台のサーバーが停止しても他の2台のいずれかから同じデータを瞬時に取得<br />Bigtableのサービスを構成するサーバー群はすべてが冗長化<br />SPoF(Single Point of Failure)を排除<br />Oracle RACなどのハイエンドのRDBクラスタに匹敵する高可用性<br />
  33. 33. Bigtableの構成要素 <br />Bigtableのテーブル <br />Bigtableのテーブルは、「分散化された多次元ソートマップ」 <br />簡単に言うと、ソート済みのExcel表のようなもの <br />個々のセルは履歴を残せる(multidimensional) <br />
  34. 34. Bigtableの構成要素 <br />Bigtableのテーブル <br />テーブルの実体は、巨大なkey-value store <br />キー:行キー+カラムキー+タイムスタンプ<br />行キーは最大64KBまで(大半は10~100バイト) <br />行キーの辞書順でソートされている <br />行単位のCRUDはアトミックに実行 <br />複数行にまたがる更新処理は原子性が保証されない <br />古い履歴データや削除された行は、自動的にGC<br />
  35. 35. Bigtableにできること<br />Bigtableにできること <br />キーを指定した行単位のCRUD <br />行単位のACID特性が保証される <br />2種類のスキャン: <br />prefix scan: キーの前方一致検索で複数行を一括取得 <br />range scan: キーの範囲指定検索で複数行を一括取得 <br />ソート済みなので高速に実行できる <br />Bigtableではカラムの値に基づく検索は一切実行できない! <br />
  36. 36. Bigtableにできること<br />
  37. 37. Bigtableの内部構造<br />Googleの典型的なクラスターノード構成<br />
  38. 38. Bigtableの内部構造<br />個々のノードの基本構成 <br />Intelベースの安いPC <br />Linux OS <br />Schedulerスレーブ <br />Schedulerマスターの指示に従ってノード上に各種サービスをデプロイする <br />GFSチャンクサーバー <br />GFSのチャンク(データ)を保存する <br />タブレットサーバー <br />Bigtableのタブレットを管理する<br />
  39. 39. Bigtableの内部構造<br />Bigtableクラスター全体を管理するサービス<br />Schedulerマスター <br />各ノードに各種サービスをデプロイする <br />Chubby <br />分散ロックサービス <br />GFSマスター <br />GFSチャンクサーバー群を統括する <br />Bigtableマスター <br />tablet server群を統括する<br />
  40. 40. Bigtableの内部構造<br />Bigtableクラスター <br />複数のBigtableテーブルからなるクラスター <br />2006年8月時点では、388のBigtableクラスターと24,500のタブレットサーバーが稼働中<br />タブレット <br />Bigtableのテーブルを分割したもの <br />テーブルの内容はタブレット単位で各タブレットサーバーに分散保存される <br />1つのタブレットは100~200MB程度のデータを保存。それ以上になると分割される <br />1台のタブレットサーバーは100以下のタブレットを保存<br />
  41. 41. Bigtableの内部構造<br />タブレット <br />復旧が高速<br />1台がダウンしても、その100個のタブレットは他の100台のサーバーが保有している <br />Bigtableマスターが負荷分散を管理<br />高負荷のサーバーからタブレットを移動 <br />
  42. 42. タブレットサーバーのメカニズム<br />タブレットサーバーの階層問い合わせ<br />
  43. 43. タブレットサーバーのメカニズム<br />タブレットサーバーの検索 <br />あるキーのデータを取得するとき<br />クライアントはタブレットサーバーのIPアドレスを取得<br />DNSライクな階層問い合わせ <br />検索の流れ<br />ブートストラップとなるChubbyサービスにアクセス<br />METADATAタブレットを持つタブレットサーバーのIPアドレスを取得<br />METADATAタブレットには、各キーに対応するタブレットサーバーのIPが記録されている <br />
  44. 44. タブレットサーバーのメカニズム<br />タブレットサーバーの検索 <br />タブレットサーバーの検索には、最大で3回のネットワーク通信が必要<br />通常はクライアント側にMETADATAタブレット内容がキャッシュされており、クライアントはタブレットサーバーに直接接続できる<br />
  45. 45. キャッシュ管理とディスクアクセス<br />Bigtableのキャッシュ構造<br />コミット<br />ログ<br />テーブルへのアクセス<br />minor compaction<br />(ディスクにflush)<br />memtable <br />(キャッシュ)<br />major compaction<br />(ゴミファイルをGC)<br />SSTable <br />(ディスク上のファイル)<br />GFS<br />GFS<br />GFS<br />
  46. 46. キャッシュ管理とディスクアクセス<br />memtableによるキャッシュ管理<br />memtableは、タブレットにコミットされた更新内容を記録するソート済みのバッファ <br />個々の更新処理はディスク上のコミットログに記録され、更新内容はmemtableに記録される <br />
  47. 47. キャッシュ管理とディスクアクセス<br />マイナーコンパクション <br />memtableがいっぱいになると、その内容がSSTableにフラッシュされる<br />(OracleのDBWR+チェックポイントと同様)<br />
  48. 48. キャッシュ管理とディスクアクセス<br />SSTableによるディスク保存<br />SSTableとは、memtableの内容保存に利用されるファイルフォーマット <br />ソート済みのイミュータブル(変更不可)なマップ(key-valueペア) <br />イミュータブルなのでファイルアクセス時のロックが不要、同時アクセスを効率的に扱える <br />コピーオンライトですばやくタブレットを分割できる<br />
  49. 49. キャッシュ管理とディスクアクセス<br />メジャーコンパクション<br />削除されたデータがゴミとして残るので、マーク&スウィープGCを実行する <br />(PostgreSQLのvacuumと同様)<br />
  50. 50. GFSの利用<br />GFSによるディスクへの書き込み <br />GFS(Google File System)とは、SSTable等のファイル保存に用いられるファイルシステム <br />ファイルは必ず3台以上のサーバーに書き込み <br />ローカルのGFSチャンクサーバーが空いていれば、そこに1つを書き込み <br />残り2つは、離れた場所(少なくとも同じラックではない場所)のGFSチャンクサーバーに書き込み <br />
  51. 51. GFSの利用<br />GFSによるデータのレプリケーション<br />
  52. 52. GFSの利用<br />GFSによるディスクへの書き込み <br />タブレットが移動しない限り、タブレットサーバーはローカルのGFSチャンクサーバーにアクセス<br />負荷分散のためタブレットが移動すると、データは残したままタブレットのみ移動 <br />バイナリアップグレード時などに、できるだけローカルに置くようにデータを再配置<br />
  53. 53. Datastoreサービス<br />
  54. 54. Datastoreサービスとは<br />App Engineにおけるデータ保存サービス<br />Bigtable上に実装されている<br />Datastoreサービスでできること<br />オブジェクトのCRUD(Create, Read, Update, Delete)<br />エンティティグループ単位でACIDを確保(後述)<br />オブジェクトのクエリ(検索)<br />JDOQLまたはGQLを使用<br />
  55. 55. Datastoreサービスとは<br />JDO APIによるオブジェクト保存の例<br />        PersistenceManager pm = PMF.get().getPersistenceManager();        Employee e = new Employee("Alfred", "Smith", new Date());        try {            pm.makePersistent(e);        } finally {            pm.close();        } <br />
  56. 56. Datastore用語<br />Datastore用語と既存用語のおおまかな対比<br />カインド(kind)<br />クラス/テーブル<br />エンティティ(entity)<br />オブジェクト/レコード<br />プロパティ(property)<br />フィールド/カラム<br />キー(key)<br />オブジェクトID/プライマリーキー<br />
  57. 57. エンティティテーブル<br />エンティティテーブルとは <br />エンティティを保存するテーブル<br />App Engine内のすべてのエンティティテーブルが1つのBigtableテーブルに格納されている<br />個々のエンティティは、キーで識別<br />キーの辞書順でソートされている<br />個々のエンティティのプロパティ内容は、すべてBigtableの1つのカラムにシリアライズされて格納 <br />Protocol Buffer形式で保存される<br />
  58. 58. キー<br />キー <br />アプリID+パス(カインド名+IDまたはキー名)<br />IDは自動採番<br />エンティティグループなし:カインド内でユニーク<br />エンティティグループあり:エンティティグループ内でユニーク<br />キー名はアプリ側で設定<br />ユニークにする必要がある<br />エンティティのキーは変更できない<br />表記例<br />Foo(25)<br />カインド名+ID(アプリIDは表示されない)<br />agR0ZXN0cgkLEgNGb28YGQw<br />protocol buffer+BASE64<br />
  59. 59. プロパティ<br />プロパティ <br />variable properties <br />エンティティごとにプロパティの数や種類を変えられる<br />「プロパティがない」と「プロパティがnull」は区別される<br />heterogenous property types <br />エンティティごとにプロパティの型を変えることができる <br />(GAE/Jでこれを使えるかは不明)<br />
  60. 60. プロパティの特徴<br />Datastoreのプロパティの特徴 <br />multiple value properties (MVP) <br />1つのプロパティにListやtupleを保存できる<br />シリアライズして保存される<br />クエリの例:name == 'Foo' <br />List内のいずれか1つの値がFooならtrueになる<br />非正規化や設計の最適化に活用できる<br />1:N関連の代わりに使う(非正規化)<br />ジョインテーブルの代わりに使う<br />Serializableオブジェクトを格納可能<br />
  61. 61. Datastoreのパフォーマンス<br />Datastoreの性能は、エンティティの数とは無関係 <br />保存されているエンティティが1件でも、1000件でも、1000万件でも、パフォーマンスに変化はない <br />エンティティへの読み書き速度<br />エンティティの読み込み:平均数10ms程度<br />エンティティの更新:平均100ms程度<br />個々のエンティティの更新処理は遅い<br />アプリケーションのパフォーマンスを決めるのは、更新処理の実装方法。参照処理は桁違いに速い <br />平均数10ms程度<br />Datastoreパフォーマンスの監視ページ<br />http://code.google.com/status/appengine/<br />
  62. 62. DatastoreサービスのAPI<br />DatastoreサービスのAPI<br />JDO (Java Data Objects)<br />オブジェクトDBの標準API<br />○:ドキュメントと実績が豊富<br />×:性能が低い(LLAPIの1/3程度)、Bigtableと乖離している<br />JPA (Java Persistence API)<br />ORMの標準API<br />×:ドキュメントや実績が少ない<br />
  63. 63. DatastoreサービスのAPI<br />DatastoreサービスのAPI<br />low-level API(LLAPI)<br />Bigtableにもっとも近い独自API<br />○:性能が高い。Bigtableを理解しやすい<br />×:低レベル。ドキュメントがあまりない<br />Slim3 Datastore<br />ひがやすを氏開発(サードパーティ)<br />○:性能が高い。高レベルで使いやすい<br />×:実績が少ない<br />
  64. 64. DatastoreサービスのAPI<br />Slim3のパフォーマンステストツールの実行例<br />
  65. 65. Datastoreのクエリ<br />
  66. 66. クエリ<br />Datastoreのクエリとは<br />複数のエンティティを条件検索できる<br />通常、160~200ms程度で処理<br />条件の記述方法<br />JDOQL<br />GQL<br />Query query = pm.newQuery("select from Employee " +                              "where lastName == lastNameParam " +                              "order by hireDate desc " +                              "parameters String lastNameParam")    List<Employee> results = (List<Employee>) query.execute("Smith"); <br />
  67. 67. Bigtableのスキャン<br />
  68. 68. クエリ=インデックス+スキャン<br />クエリは「インデックス+スキャン」で実装 <br />Bigtableはクエリをサポートしていない<br />「値」に基づく検索を実行できない<br />すべてのクエリは、インデックスとスキャンの組み合わせで実現<br />すべてのクエリの検索結果をあらかじめインデックステーブルに並べておく<br />
  69. 69. 3種類のインデックス<br />Datastoreのインデックスとは<br />エンティティテーブルとは別のテーブル<br />3種類のインデックス<br />カインドインデックス <br />シングルプロパティインデックス <br />コンポジットインデックス <br />
  70. 70. カインドインデックス<br />カインド名順でソートされたインデックス <br />あるクラスのすべてのエンティティの一覧を提供 <br />例:Empでカインドインデックスをスキャン <br />SELECT * FROM Emp<br />
  71. 71. カインドインデックス<br />
  72. 72. シングルプロパティインデックス<br />「エンティティの個々のプロパティ値」でソートされたインデックス<br />すべてのプロパティについてデフォルトで作成<br />インデックス不要なプロパティを明示できる<br />昇順用と降順用の2つが作成される<br />1つのプロパティを条件に検索/ソートできる<br />例:name == ‘佐藤' <br />例:ORDER BY name <br />例:age >= 20 AND age <= 40<br />
  73. 73. シングルプロパティインデックス<br />
  74. 74. コンポジットインデックス<br />「複数のプロパティ値の組み合わせ」でソートされたインデックス<br />「カスタムインデックス」とも呼ぶ<br />自動定義または手動定義<br />複数のプロパティ値で検索できる<br />例:dept_key = D1 & age >= 30 & age <= 40<br />「Emp/D1/30」から「Emp/D1/40」までrangeスキャン<br />「 < <= > >=」などの不等号条件(inequality filter)は、ひとつのプロパティに対してのみ利用可能<br />
  75. 75. コンポジットインデックス<br />
  76. 76. コンポジットインデックス<br />コンポジットインデックスのデメリット <br />すべてのプロパティ値の順列組み合わせでインデックス内容が作成されるので、インデックスサイズが膨大になりやすい <br />クエリを多用/誤用するとインデックスが増え、更新処理が遅くなる<br />multi-value property利用時のインデックス爆発(index explosion)<br />「ここぞ」という用途に限って使うべき<br />できるだけコード上でのフィルタリングやソートがよい<br />
  77. 77. マージジョイン<br />マージジョイン(merge join)とは <br />複数プロパティの等号条件(equality filter)検索をコンポジットインデックスに頼らずに実現<br />例:dept_key = D1 & age = 40 & name = ‘佐藤’<br />複数のシングルプロパティインデックスをマージしながら検索<br />"zig-zag"アルゴリズムにより、個々のインデックスを並行してスキャン <br />
  78. 78. マージジョイン<br />zig-zagアルゴリズムによるマージジョイン<br />
  79. 79. Datastoreを構成するBigtable<br />Datastoreサービスを構成する7つのBigtable<br />Entitiesテーブル<br />すべてのアプリのエンティティを保持<br />EntitiesByKindテーブル<br />EntitiesByPropertyASCテーブル<br />EntitiesByPropertyDESCテーブル<br />EntitiesByCompositePropertiesテーブル<br />カスタムインデックステーブル<br />ID sequencesテーブル<br />
  80. 80. Entitiesテーブル<br />キー<br />App ID+パス(カインド名+IDまたはキー名)<br />プロパティ<br />プロパティ名+プロパティ値のペア<br />Protocol Buffer形式<br />メタデータ <br />ルートエンティティのキー、カインド名<br />カスタムインデックスデータ<br />インデックスID、祖先エンティティのキー一覧、プロパティ値一覧<br />
  81. 81. インデックステーブル<br />EntitiesByKindテーブル<br />カインドインデックスを保持<br />App ID、カインド名、エンティティキー<br />EntitiesByPropertiy ASC/DESCテーブル<br />シングルプロパティインデックスを保持<br />App ID、カインド名、プロパティ名、プロパティ値、エンティティキー<br />EntitiesByCompositePropertyテーブル<br />コンポジットインデックスを保持<br />インデックスID、App ID、カインド名、祖先エンティティのキー一覧、プロパティ値一覧、エンティティキー<br />
  82. 82. その他のテーブル<br />カスタムインデックステーブル<br />コンポジットインデックスの定義を保持<br />ID sequencesテーブル<br />ID採番用<br />
  83. 83. クエリの制限<br />テーブル間のjoinができない <br />非正規化して対処する <br />「正規化するな、JOIN済みのでっかいテーブルを作れ」 <br />select * from PERSON p, ADDRESS a<br />where a.person_id = p.id and p.age > 25 and a.country = “US”<br />↓<br />select from com.example.Person where age > 25 and country = “US”<br />複数のクエリに分割する <br />multiple value propertyを使う <br />
  84. 84. クエリの制限<br />集約関数がない(group byできない) <br />count()で全件カウントできない <br />毎回対象データをすべて取得してループで集計するのは非効率<br />集約したい値は、集約用のエンティティを用意して集計 <br />sharding counter: 書き込みが集中しないように複数のエンティティに分散して書き込みし、後で集計 <br />memcache counter: memcacheに書き込みし、Task Queueでエンティティに保存 <br />
  85. 85. クエリの制限<br />集約関数がない(group byできない) <br />max()/min()で最大値/最小値を得られない <br />対象プロパティで降順/昇順でソートして、1件目の値を得る <br />
  86. 86. クエリの制限<br />関数やストアドプロシージャはない <br />toUpper/toLowerなどがない <br />別のプロパティを設け、toUpper済みの値を入れる <br />書き込み時にできるだけ事前処理を行っておくことで、読み込みを高速化できる <br />
  87. 87. クエリの制限<br />クエリの構文の制約 <br />全文検索ができない <br />LIKEによる部分一致検索はできない <br />前方一致なら可能: name >= 'a' AND name <= 'a<UTF-8コードポイントの最大値>' <br />検索対象の文字列を形態素解析し、ワードごとのインデックスを作成する<br />2010年に全文検索対応予定?<br />
  88. 88. クエリの制限<br />そのほかの制約 <br />OR、!=が使えない<br />近日対応予定<br />inequality filters (< <= >= >)は1つのプロパティにのみ利用可能<br />Text型やBlob型のプロパティはインデックスを作成できない(クエリできない)<br />あるプロパティでinequality filtersを使うと、他のプロパティを最優先にしたソートができない<br />
  89. 89. Backup Slides<br />
  90. 90. Datastoreのトランザクション<br />
  91. 91. エンティティグループとは<br />エンティティグループとは<br />エンティティ間の親子関係<br />親(parent)と子(children)<br />子のキーに親のキーを埋め込む<br />最上位の親はルートエンティティ(root entity)と呼ばれる<br />親は変更できない<br />デフォルトでは<br />個々のエンティティは個別のエンティティグループ(ルートエンティティ)となる<br />Dept<br />1<br />*<br />Emp<br />
  92. 92. エンティティグループとキー<br /> /Grandparent:123 <br /> /Grandparent:123/Parent:52<br /> /Grandparent:287 <br /> /Grandparent:287/Parent:85<br /> /Grandparent:287/Parent:88/Child:47<br /> /Grandparent:287/Parent:88/Child:66 <br />カインド名<br />ID<br />親のキー<br />パス<br />
  93. 93. エンティティグループとは<br />エンティティグループの指定方法<br />明示的な指定<br />子のキーを、親のエンティティのキーを使って生成する<br />詳しい手順:http://d.hatena.ne.jp/uehaj/20090509/1241856856 <br />JDOのowned関係<br />UserとAddress間で親子関係を定義<br />unowned関係はサポートしていない <br />エンティティグループが個別になるのでACIDを保証できないため <br />OOPやRDBの「関連(リレーション)」とは無関係<br />関連をそのまま当てはめると問題も(後述)<br />
  94. 94. エンティティグループとは<br />エンティティグループの2つの役割<br />ローカリティを指定する<br />パフォーマンスの向上<br />トランザクション・スコープを指定<br />ACIDの保証<br />CAP定理とエンティティグループ<br /> 特定範囲(ローカリティ)のみを対象にACID保証<br />ACID<br />001 abc<br />002 def<br />
  95. 95. ローカリティ<br />ローカリティ<br />エンティティグループのすべてのエンティティは、1つのサーバーに保存される確率が高い<br />より高いパフォーマンスが期待できる<br />参考:http://groups.google.com/group/google-appengine-java/browse_thread/thread/fd758c65e14b5c76/e4afc1e348a36a36?show_docid=e4afc1e348a36a36<br />大量のエンティティがある場合は複数サーバーに分割<br />GFSによりデータは他2カ所にバックアップされる<br />キー順でソートされている<br />/Grandparent:Alice <br />/Grandparent:Alice/Parent:Sam <br />/Grandparent:Ethel <br />/Grandparent:Ethel/Parent:Jane <br />/Grandparent:Ethel/Parent:Jane/Child:Timmy <br />/Grandparent:Ethel/Parent:Jane/Child:William <br />/Grandparent:Frank<br />
  96. 96. トランザクション・スコープ<br />Datastoreのトランザクション・スコープ<br />トランザクションの開始(begin)と終了(commit/rollback)を指示する<br />エンティティ・グループ<br />エンティティグループ単位でACIDを保証 <br />Bigtableは行単位のACIDしか保証しない<br />Datastoreではエンティティグループ単位でのACIDを保証している<br />SERIALIZABLE相当<br />異なるエンティティグループ間では保証されない <br />
  97. 97. DatastoreとBASE<br />楽観的排他制御(optimistic lock)を実装 <br />エンティティグループのルートエンティティにて、トランザクションの最終コミット時間のタイムスタンプを記録 <br />トランザクションの開始時に同タイムスタンプを確認<br />コミット時にタイムスタンプを再度確認する <br />タイムスタンプが変化していなければ、更新内容を保存して、タイムスタンプを更新<br />タイムスタンプが変化してれば、他のトランザクションとの競合が発生しているので、トランザクションをロールバック<br />
  98. 98. DatastoreとBASE<br />楽観的排他制御(optimistic lock)を実装 <br />RDBの悲観的排他制御(SELECT FOR UPDATE)のようにエンティティをロックしない<br />スループットは高いが、競合時のリトライが必要<br />Python版は3回まで自動リトライし、Java版は自動リトライしない <br />
  99. 99. DatastoreとBASE<br />リトライの例<br />        for (int i = 0; i < NUM_RETRIES; i++) {            pm.currentTransaction().begin();            ClubMembers members = pm.getObjectById(ClubMembers.class, "k12345");            members.incrementCounterBy(1);            try {                pm.currentTransaction().commit();                break;            } catch (JDOCanRetryException ex) {                if (i == (NUM_RETRIES - 1)) {                     throw ex;                }            }        } <br />
  100. 100. DatastoreとBASE<br />分散トランザクションへの対応 <br />App Engineでは異なるエンティティグループ間の分散トランザクション(グローバルトランザクション)はサポートされていない<br />ただしアプリレベルでの実装例はある <br />http://code.google.com/intl/ja/events/io/sessions/DesignDistributedTransactionLayerAppEngine.html <br />http://code.google.com/intl/ja/events/io/sessions/TransactionsAcrossDatacenters.html <br />
  101. 101. トランザクションの注意点<br />1 TX = 1 エンティティグループ<br />1つのトランザクション内では、1つのエンティティグループの更新処理しか実行できない<br />複数のエンティティグループを更新する場合は、個別のトランザクションが必要<br />=ルートエンティティの更新は個別TXが必要<br />1つのエンティティの更新は1回まで<br />1つのトランザクション内では、1つのエンティティを複数回更新できない<br />
  102. 102. トランザクションの注意点<br />トランザクション内で実行可能なクエリの制限<br />ancestor filterを持つクエリのみ実行可能<br />コミット前の値は読み込みできない<br />READ_COMMITTED相当<br />http://code.google.com/intl/ja/appengine/articles/transaction_isolation.html <br />http://groups.google.com/group/google-appengine-java/browse_thread/thread/4a67044929428295 <br />
  103. 103. エンティティグループのボトルネック<br />1つのエンティティグループにトランザクション負荷を集中させない<br />エンティティグループの利用は必要最小限に抑えた方が性能は向上する <br />リレーショナルモデルやオブジェクト指向の関連をそのままあてはめると問題が生じることも <br />Dept<br />1<br />*<br />Emp<br />
  104. 104. エンティティグループのボトルネック<br />例:1つのDepartmentと1000のEmployee<br />1000のEmployeeのうち、いずれか1つのEmployeeしか同時にトランザクションを実行できない<br />他はエラーとなりリトライが必要<br />例:1つのUserと数個のAddress<br />1人のユーザーの住所に対して複数のトランザクションが同時実行される頻度は低い<br />負荷は集中しない <br />

×