これは Fujitsu Advent Calendar 2017 の 23 日目の記事です。
はじめに
こんにちは。筆不精で記事を書かずにいたら、もう1年もたってしまったことに軽く驚いています。軽くしか驚かないところがだめですね。
今回は、PostgreSQLでのマルチモデルの取り組みを紹介します。2017年12月4日から6日まで秋葉原で、アジアを代表するPostgreSQLのカンファレンスであるPGConf.ASIAが開かれました。昨年の同イベントでのLTに引き続き、今年は40分の講演をさせていただきました。 そのプレゼン資料 をもとに、講演でお話したことを短めにかいつまみつつ、しゃべらなかったことも補足します。
マルチモデルというのはキーバリューや文書、グラフといった複数のデータモデルを扱える能力のことです。データベース業界ではここ1、2年でホットなキーワードになってます。
じわじわ人気が上がってホットになってきているPostgreSQLを、さらに人気にして飛躍させるためにも、マルチモデルの取り組みを促進したいと思っています。
なお、さまざまなデータベースの人気を集計しているDB-Engines.comというサイトによれば、PostgreSQLの人気は昨年の同時期と同じ第4位です(2017年12月10日時点)。ただ、下記ページのランキングをご覧ください。上位3つのデータベースであるOracleとMySQL、SQL Serverが人気点数を落とす中、PostgreSQLの人気は大きく上がっています。昨年は4~5倍もの人気差がありましたが、今はなんと、Oracleとの人気差は3.5倍を切り、SQL Serverとの差は3倍に縮まりました!5位のMongoDBの人気は、昨年はPostgreSQLとほぼ同じでしたが、今は差が開いてきています。
なぜマルチモデルが必要か?
ビッグデータの一要素としてのデータ多様性
結論からいうと、多様な形式のビッグデータを扱うことが欠かせなくなってきているということです。
ビッグデータの特徴をおさらいすると、それは3つのVであらわされます。この起源は、2001年のGartnerの調査レポートです。今から16年も前で、2004年のFacebook創業より前からいわれてるんですね。
- Volume: データの量の多さ
- Velocity: データの出し入れや処理の速さ
- Variety: データの種類やデータソースの多様さ
マルチモデルはvarietyにかかわります。ちなみに、他の人がVeracity(正確さ、精密さ)やValue(価値)を付け足して4Vやs5Vsといわれることもありますが、後付け感があるのでここではそれらを扱いません。
PostgreSQLはビッグデータを扱えるのか?
今のPostgresでビッグデータを扱うために、どんなものが利用できたり、あるいはどんな開発が進められているでしょうか。
まずデータの量については、パーティショニングが利用できます。2017年にリリースされたPostgreSQL 10から、本格的なパーティショニング機能が利用できるようになりました(NTTのAmit Langoteさん、ありがとう)。PostgreSQL 11に向けては引き続き、ハッシュ・パーティショニングやさまざまな性能改善が取り組まれています。PostgreSQL 11での取り組みについては、次のブログ記事で知ることができます。
スケールアウトを可能にする Postgres-XL や Citus といった外部プロジェクトもあります。Postgres-XLはPostgreSQLからフォークしたものなので、PostgreSQLの最新版に追従することに難があります。2017年12月17日時点での最新はPostgreSQL 9.5.8ベースです。一方、Citusは拡張モジュールとして組み込めます。
次にデータの高速な処理については、GPUで並列処理するための PG-Strom や、ストリーミング処理ができる PipelineDB などがあります。富士通からはコミュニティに、インメモリカラムナの機能(VCI: Vertical Clustered Index)を提案しているところです。なお、PG-StromとVCIは拡張モジュールであり、PipelineDBはフォークです。
そしてデータの多様性については、キーバリューを扱うための hstoreデータ型 や、JSONデータのための jsonbデータ型 があります。このhstoreやjsonb型によって、PostgresもNoSQLの機能を備えてきた、なんていわれています。
NoSQLの人気の高まり
ビッグデータはRDBでは扱えない、としてここ7、8年人気を高めてきたのが、NoSQLといわれるデータベース群です。ClouderaやMongoDBといったおなじみの会社が、2017年に株式上場を果たしたりしましたね。
The Forrester Wave: Big Data NoSQL, Q3 2016 のFigure 1を見てください。これは、データと分析の技術に関する世界の意思決定者2094人に、NoSQLを使っているか、あるいは関心があるかをたずねた結果です。実に8割もの人が、NoSQLをすでに使っている、または関心があると回答しています。
そんなNoSQLが受けている理由は、次の3つです。
- 開発生産性のよさ。現実世界のものを素直にデジタルで表現しようとすると、二次元の表の形だけでなく、配列やリスト、グラフ、オブジェクトの階層といったデータ型を使いたくなります。NoSQLは、アプリが扱いたいモデルのままでデータを格納できるので、ORMなどを使って無理にリレーショナルの形に変換する必要がありません。このデータモデルの柔軟性がマルチモデルにかかわる部分です。
- スケールアウトが容易で、たくさんのデータや処理を捌けること。
- サーバやストレージが故障しても、他のサーバがデータや処理を提供し続ける耐障害性を容易に実現できること。
そんな中、さまざまなデータモデル用のNoSQLデータベースが登場してきました。スライド "Data Models" の表に、データモデルとその代表的なデータベースを挙げてみました。赤字にしているキーバリューと文書、グラフは目にすることが多いと思います。
ちなみに、講演で「これらのデータモデルすべてを使ったことがある、もしくは知っているという方は手を挙げてみてもらえますか?」とたずねてみたら、手を挙げたのはわずか2人でした。さすがに「ほとんどいないだろう」とは思いつつ、逆に2人の方はすべて知っていたということで、データベースのイベントらしいと感じました。
Polyglot persistenceとその問題
このようにさまざまなデータベースが登場してくると、1つのシステムやアプリケーションの中でも、データごとに最適なDBMSを使い分けよう、何もすべてにRDBを使うことはない、という動きが出てきました。それをPolyglot persistenceといいます。2011年に Martin Fowlerがこの言葉を取り上げて 広まってきました。ちなみにpolyglotとは、複数の言語を話すという意味です。
たとえばオンラインショッピングのシステムでは、5つのデータモデルを使ったりするということです。顧客や注文といったがっちりしたデータはRDBで管理したり、Webセッションやショッピングカートといった高速だけど単純なアクセスが必要なデータはキーバリューストアで、製品ごとに属性が異なるカタログデータは文書データベースで、Webアクセス履歴はワイド列ストアで、レコメンデーションのためのデータはグラフデータベースで、といった具合です。
先進企業はこのPolyglot persistenceにのっとって、たくさんのDBMSを使い分けています。たとえば動画配信のNetflix。彼らは何百ものマイクロサービスを動かしてますが、その裏でスライド"Multiple DBMSs use"に挙げたDBMSを使うそうです。
しかも、自分たちでもDBMSを作ってしまったり、さらにそれをオープンソースで公開したりしています。GoogleやAmazon、Facebookなどもそうですよね。おかげでCassandraやHBaseといったNoSQLデータベースが利用できています。
このPolyglot persistence、データごとに最適なデータモデルを使うというのはよいのですが、異なるDBMSを使うというところに次のような問題があります。
- データがサイロ化するため、横断的なデータ活用がしづらいです。しようとすれば、ETLなどで1箇所にデータを集めることになります。労力や時間がかかりますし、リアルタイムにもなりにくいです。
または、アプリケーションが複数のDBMSからデータを持ってきて、それらを結合したり、集計やソートをせねばなりません。 - 異なるDBMS間でのデータ更新をどうアトミックにするか、どうやって一貫した状態のデータを読むか、というデータ整合性です。
- インフラのコストがかさむことです。これは分析のためにデータをコピーしたり、DBMSごとにハードウェアやVMを分けたくなるからです。
- 構築や運用が複雑になること。主にデータベース管理者の負担が増すという話です。DBMSごとにライセンスやベンダ契約の管理から始まって、インフラの用意や配備、パッチ適用、設定があります。ユーザ管理や監査などセキュリティもしっかりやらねばなりません。日々の監視と問題解決、性能チューニングもあります。これらの負担はクラウドで軽減されるとはいえ、ゼロにはなりません。
それに、一番難しいのが、一貫した状態でリカバリしたい、というHAはどうするか?バックアップはDBMSごとに別個にとりますよね。レプリケーションのラグもDBごとにまちまちです。そんな中で、過去の時点にデータを戻したいとか、災害対策用のサイトに切り替えたいといったら、どうやればいいんでしょう?できるでしょうか? - アプリ開発者もDBMSごとの独自APIやトランザクション制御、くせやチューニング方法を学ばねばなりません。多くのNoSQLデータベースがSQLに似たクエリ言語を提供するようになったとはいえ、それらはあくまで「SQLに似て非なるもの」です。SQL標準に準拠してきた従来のRDBでさえ、DBMSごとのSQLの違いのために、学習やアプリの移植はなかなか難しいのですから、推して知るべしです。
- 複数のDBMSを扱える人材の確保です。NetflixやUberのような人気の先進企業なら優れた技術者をたくさん集めて、いろいろなDBの使い分けもできるでしょうが、その他の多くの組織にとっては、人材不足といわれる昨今、なかなかそうはいきません。
マルチモデル・データベースとは?
そこで、polyglot persistenceのこれらの問題を解決するのがマルチモデルデータベースです。マルチモデル・データベースとは、複数のデータモデルを扱えるDBMSのことです。
ちなみに、マルチモデル・データベースは一般用語で、 英語のWikipediaにものっています 。日本語のWikipediaにはまだないようです。PGConf.ASIAのアンケートでも、知っている人は少なかったです。私の周囲にもいませんでした。Gartnerは数年前からマルチモデルという言葉を使っているのですけどね。
メリットは、直観に訴えるひとことでいうなら、「スマートフォンのように全部入りでとても便利」ということです。個別のメリットは先ほどの問題点の裏返しなので述べません。想像しやすいですよね。iPhoneかAndroidフォンのどちらかの使い方(起動・停止、設定、認証方法、バックアップなど)を覚えれば、いろいろなアプリが使える、あの便利さです。データベースもマルチモデルでスマフォ化の時代です。
世の中には、マルチモデルをうたうデータベースは少ないながらも存在します。先述のWikipediaページや、スライド"Multi-model Database Examples"にいくつか例があります。
この中で注目したいのは、Microsoftが2017年に発表して最近よく見かけるCosmos DBです。それと、エンタープライズ向けのNoSQLとして、データ統合の用途で注目されているMarkLogicでしょうか。NTTデータが2017年にMarkLogic社との資本業務提携を結ぶなど、日本での存在感も高まってきた気がします。
主要なDBMSでのマルチモデルの取り組み状況
DB-Enginesの人気ランキングで上位5つのDBMSについて、主なデータモデルのサポート状況をスライド"Trends of Major DBMSs"の表に示しています。この表で+が2つは「よい」の意味で、+1つは「いまいち」、空欄は「そのデータモデルをサポートしてない」という意味です。「いまいち」としているのは、クエリ言語やAPIがそのデータモデルで標準的でないとか、仕組みが期待される性能を発揮できるものでないということです。
昨年から今年にかけて、どのDBMSも文書モデル(JSON)の追加や強化をしてきてます。Oracleは自社の仕様をSQL/JSONとしてSQL:2016で標準化しました。また、商用DBMSではグラフモデルがブームです。Oracle Databaseの最新版12c Release 2やSQL Serverの最新版2017は、プロパティグラフをサポートするようになっています。
Postgresに「よい」がなくて、ちょっと評価が厳しいのでは?と思うかもしれませんが、性能や標準性を考えると実際そうです。
PostgreSQLをマルチモデル・データベースに
そんな我らがPostgresをマルチモデルデータベースとして成長させ、より多くの用途で使えるようにしたいというのが私の思いです。PGConf.ASIAの基調講演をされたロシアのOlegさんも、ご自身の講演で同じような思いを語っていて、うれしくなりました。ああ、一人じゃないんだ、と。ちなみにOlegさんは、PostgreSQLにJSONサポートを導入してこられた方です。
では、NoSQLがたくさんある中でなぜRDBをもとにするか。それは、20年以上にわたって厳しい環境で磨かれて、ストレージエンジンが成熟してきたり、オプティマイザが賢いということがあります。これは他のデータモデルでも活きてきます。実際、JSONデータの挿入や検索で、 Postgresの性能がMongoDBの2倍から3倍よかったという評価結果 もあります(ただし、MongoDBは2.6と古い。デフォルトのストレージ・エンジンがWiredTigerとなったMongoDB 3.2以降と比べるとどうだろう?)。
それになんといっても、最も普及したRDBがマルチモデルになれば、多くの人が使う機会を得やすいと思うからです。iPhoneのKindleアプリのおかげで、私は電子書籍の読書を楽しむようになりました。それと同じです。
ではなぜPostgresなのか。なんといっても拡張性の高さです。PostgreSQLはデータ型やインデックスをはじめ、いろいろな部分を拡張できるので、多様なデータを扱うプラットフォームとしての発展を期待できます。
PostgreSQLでマルチモデルをどう実装する?
データモデルとは
まず、データモデルとは何でしょう?データモデルは次の3つから構成されます。
- データ構造: リレーショナルモデルであれば行と列からなる表のことです。キーバリューモデルならキーと値ですし、グラフモデルならノード、ノードどうしの関係、それにノードのプロパティやラベルとなります。
- 制約: 正しい値であるための規則のことです。一意性制約や参照制約などです。
- 操作: リレーショナルモデルであれば表や索引を読み取るスキャンであったり、2つの表のジョインなどです。キーバリューモデルならキーを指定したデータの取り出しと格納です。グラフモデルには、ノード間の関係のパターンにマッチするグラフ探索などがあります。
それと、利用者がこれらを表現するのに使うクエリ言語やAPIの話もあります。たとえばリレーショナルモデルならSQLやJDBCです。
方針としては、SQLを拡張したPostgres独自の言語を作るのでなく、データモデルごとによく使われる既存の言語を組み合わせて使えるようにするのがよいと考えています。なぜなら、アプリ開発者がスキルやノウハウ、開発資産を活かせるからです。それに、学習のための情報が豊富だったり、エコシステムを築きやすいためでもあります。
つい最近も、MicrosoftのCosmos DBがMongoDBのAPIに加えて、CassandraのAPIのサポートを発表したりしました。別のおもしろいところでは、 BigDAWG という研究プロジェクトがあります。これはIntelの研究所が米国のいくつかの大学と共同で進めているプロジェクトです。データベースの権威であるMichael Stonebraker氏も名を連ねています。BigDAWGは、各データモデルに適したDBMSに分散して格納されているデータを、単一のクエリで横断的に分析することを可能とします。BigDAWGでも、各データモデル用のクエリ言語を1つのクエリ内で組み合わせて使えるようにしているのです。
つまり、データモデルを実装するということは、データの構造・制約・操作とクエリ言語/APIを実装することです。
マルチモデルのやり方
では、どうやってデータモデルをサポートするか。2つのやり方があります。
1つ目はFlexible Schema Data(FSD)と呼ばれるものです。 Oracleの人が論文でこのように名前を付けました。
実はFSDはJSONやXMLでおなじみですし、PostGISなどの地理空間データもこれです。RDBのユーザ定義データ型を使ってテーブルの列にデータを入れます。それから、ユーザ定義の関数とインデックスを使って、SQLでアクセスします。
2つ目のやり方は、データモデルごとにクエリ言語や全体的な処理が異なる場合のものです。グラフモデルやRDFなどで使います。
基本的には、クエリ処理系のパーサからストレージエンジンまでデータモデルごとに独立です。一方で、RDFモデルのように、SPARQL言語用のパーサだけ用意して、以降の処理はリレーショナルモデルの部品を使って、データはRDBのテーブルに入れる、という構成もあるかと思います。構成は、どこまでモデルごとに最適化を突き詰めるかしだいです。
こうやって複数のデータモデルの実装を混在すると、モデル専用のDBに比べて性能が出ないのではないかと心配するかもしれません。でも、それぞれのモデルの処理は独立していて他のモデルに邪魔されないので、性能はだいじょうぶ(なはず)です。
この2つ目のやり方にそった形でデータモデルを実装したものが、わずか2つですが、Postgresの世界にあります。
1つはグラフモデルを実装した AgensGraph というものです。韓国のBitnine Global社が開発しています。PostgreSQLからフォークしています。
もう1つは時系列モデルの TimescaleDB というものです。プリンストン大学の教授がTimescale社を立ち上げ、CTOをしながら開発しています。こちらは既存のPostgreSQLに拡張モジュールとして導入できます。
プラガブル・データモデル
2つ目のやり方でのデータモデルを充実させるために、データモデルを拡張モジュールとしてプラガブルにすることを提案しています。こうすることで、Postgres本体のコミュニティではなかなか取り組めないニッチなデータモデルも、コミュニティ外部で利用実績を積んでいずれ本体に統合、ということも望めます。
このために、次の3つのユーザ定義オブジェクトを導入します。
- クエリ言語: クエリ文字列を解析してパースツリーを生成します。
- データモデル: パースツリーから問い合わせ計画を生成し、それを実行します。
- リージョン: クエリ言語とデータモデルの組み合わせです。なぜリージョンが必要かというと、グラフモデルのように、1つのモデルにも複数のクエリ言語がありうるからです。OSのロケールの概念に似ていると考えればわかりやすいかと思います。
複数のデータモデルをまたぐクエリ
マルチモデルの醍醐味の1つとして、1つのクエリで複数のモデルのデータを結合できるようにします。スライド"Multi-model Query"にクエリ例を書きました。
これは、東京にある中華レストランのうち、Taroさんの友人の友人までの間で人気上位5店を挙げるものです。この例では、レストランの種類や場所は、リレーショナルのレストラン表にあります。一方、人と人との友人関係や、ある人がこのレストランを好きだという関係は、グラフモデルで管理しているとします。
このクエリでは、外側のSQLでレストラン表を検索します。そのSQLの内側で、サブクエリとしてグラフのクエリを実行しています。
赤いところで、in_region関数にリージョン名とグラフのクエリ文字列を指定して、Taroの友人たちが好きなレストランと好きな人の数を取り出します。次に青いところ、cast_region関数でグラフ形式のサブクエリ結果をリレーショナル形式に変換します。あとは外側のWHERE句でレストラン表とジョインしてます。
その次のスライド"Mixed-model Query Execution"の図が先ほどのクエリを、内部でどんな問い合わせ計画として実行するかを示したものです。
右下の赤いところ、2つの計画ノードが、グラフモデルの部分です。Taroさんをノードスキャンで探して、Taroさんの友人と、その人たちが好きなレストランをパターン照合でたどります。
そして、左下がリレーショナルのレストラン表のスキャンです。ここで東京の中華レストランに絞ります。そして、左右の結果を上でジョインして、最後に一番上の計画ノードで好きな人の多い順にソートします。
このように計画ノードにつけたモデルのタグをもとに、各データモデルのエグゼキュータを呼び出しあって連動します。
文書モデルの個別トピック
Postgresは他のRDBに先駆けて、2012年からJSONをサポートしてきました。ただ残念なことに、2016年12月に発行された新しいSQL標準「SQL:2016」では、まったく違う仕様がSQL/JSONとして標準化されてしまいました。Oracleが提案したものなので、Oracle Databaseは標準に準拠していることになります。MicrosoftのSQL Serverも、部分的に準拠しているように見えます。
このSQL/JSONがPostgreSQLのJSON機能と異なる主な点は、JSONデータは文字列またはバイナリ列に格納するとか、アクセスにはJSONパス言語というのを使うというところです。
スライド"Document Model"に、クエリの記述例を示しました。左がPostgresでのクエリの記述例、右がSQL標準での記述例です。
どうでしょう、右のほうがわかりやすいのではないでしょうか。左だと、直観的でない演算子の意味を覚えてないといけませんね。右のほうは、JSON_VALUE()などの関数名はわかりやすいですし、JSONパス言語もXPathやjQueryなどでなじみやすいかもしれません。
よいニュースとして、コミュニティでは2018年リリース予定のPostgreSQL 11に向けて、この SQL標準への準拠が進められています 。悪いニュースは、ソースコードの変更量が15,000行ほどもあるので、レビューが進みません・・・。腕に覚えのある人、ぜひレビューとテストにご協力ください。
グラフモデルの個別トピック
グラフモデルで大事なのは、グラフ探索を速くするために、データ構造を最適化することです。これがNeo4jのようなグラフ専用のDBMSと、RDBMSでのグラフのサポートとを分けるものと考えています。
スライド"Graph Model"をご覧ください。たとえばソーシャルネットワークのような友人関係をRDBのテーブルであらわすと左のようになります。これだと、友人関係をたどるたびにインデックスを検索するので遅いんですね。一方、右はレコード間のポインタを使って、素直にグラフを表しています。これだと、インデックスなしで関係をたどるので速いんです。
このように、グラフモデルで性能を最大化するには、ストレージエンジンまで開発することになります。
キーバリューモデルの個別トピック
キーバリューは少し毛色が異なります。
PostgreSQLでキーバリューといえばhstoreデータ型があります。hstore型の列の中にキーと値のペアを複数入れられるものです。
しかし、キーバリューといえばWebセッションやユーザプロファイルなど、1台のサーバで秒間100万以上の高速なアクセスが期待されると思います。hstoreだとSQLを実行するので、そこまでの性能はなかなか出ません。APIもPostgres独自なので、なじみがないでしょう。
そこで、キーバリューで一番人気といえばRedisということで、バックグラウンドワーカーとしてRedisを動かし、RedisのAPIでテーブルにアクセスできるようにします。スライド"Key-value Model"の図の構成、どこかで見たことあると思った人は正解です。そう、 MySQLでのMemcached API のようなものです。
終わりに
今のPostgreSQL周辺でどんなデータモデルが利用できるかや、今後マルチモデルのためにやっていきたいことを書きました。妄想が多いですが、その妄想をできるだけ早く形にしていくようがんばります・・・!?
0 件のコメント:
コメントを投稿