SQLの実行モデルは遅い?
SQLはインターフェースと実装が分離されており、DBMSが自動で最適なアルゴリズムを探索します。だから、SQL実行ごとにアルゴリズムを探索していたら遅いのではないか、という懸念が生まれます。
そこから派生したパラダイムがKey Value Store(KVS)に代表されるNoSQL(No SQL:「SQLではない」という意味)というAPIのデータベース・モデルです。KVSの長所はAPIが用意されている処理が速いことですが、これはAPIが固定であるためアルゴリズムも固定になるためです。SQLの実行モデルで必要だったアルゴリズムの探索が不要になるというわけです。
その代わり、KVSで用意されているAPIによるデータへのアクセス・パスは極めて限定的で、リレーショナル・モデルでいうところのプライマリ・キーの完全一致アクセス・パスしかほぼ実装されていません。KVSは単一の要素を指定してアクセスするのは高速ですが、それから外れたことを苦手としています。
では、SQLの実行モデルは本当に遅いのでしょうか。多くのDBMSは一度作成したSQL実行計画をメモリー上にキャッシュする機能を持っています。SQL文の形が決まればアルゴリズム探索処理を省略し、キャッシュされたSQL実行計画でデータにアクセスします。
Oracle Databaseを例に挙げると、オンライン・トランザクション処理で使用されるような単純なSQLの実行時間は、サーバー側のプロセス上で経過する時間は約100μ秒前後です。これはサーバー間ネットワークのpingコマンドのレイテンシとだいたい同じです。
データベースの1件ごとにアクセスするためにネットワーク越しにサーバーに繰り返しリクエストを発行するようなアプリケーション・コードを記述すると「遅い」になります。「N+1問題」と呼ばれるコードがこのパターンです。
ネットワークの往復を増やさないために、1アクセスにつき1行取得ではなくSELECT文で複数行取得できるように記述するべきですし、複数の表にアクセスするたびにSELECT文を発行するのではなく、結合(JOIN)できる意味の場合は結合してSELECT文1回にした方が高速になります。
たとえば、従業員ごとの勤務地を、SQLでJOINを使い確認してみます。
SELECT 従業員.氏名, 部門.所在地 FROM 従業員, 部門 WHERE 部門.部門ID = 従業員.部門ID ORDER BY 従業員.氏名;
ここではSQLの構文解説は省略しますが、従業員の取り出しに加えて部門IDが合致する部門情報の突き合せと名簿順並び替えをデータベース側で行い、アプリケーションに結果を返します。アプリケーションのコードはシンプルです。
また、Oracle DatabaseはSELECT文が複数行返す場合、結果セットから実際に行データを取り出すFETCH操作は複数行をバースト転送します。1件取得するたびにSELECT文を発行するのではなく、SELECT文が結果集合を返すという概念を素直にコーディングするとネットワーク往復が少ない動作になります。
データベース・サーバー側のプロセス上の経過時間は短ければ短いほどアプリケーション開発者にはうれしいわけですが、100μ秒からさらに減少させることができたとして、ネットワーク往復時間の方が大きくなってしまいます。
オンライン・トランザクション処理向けのイン・メモリーDBMSであるOracle TimesTenはサーバー側での処理時間が1桁μ秒(Oracle Databaseの1/10、だからTimesTen)という極めて小さなレイテンシです。しかしアプリケーション・サーバーとデータベース・サーバーをネットワーク接続するとこれだけ小さなレイテンシを活かすことができません。そのためOracle TimesTenはアプリケーション・サーバー・ソフトウェアと同一OS上で動作させることを想定しています。
一般的にKVSはデータベース・サーバー内での処理時間の短さを特徴としていますが、用意しているAPIは基本的にプライマリ・キーを指定した1要素にアクセスするものです。このアクセス・パスから外れたクエリーが必要になった場合、データベースからアプリケーションに何往復もしてデータを読み込み、アプリケーション側でデータ操作をするアルゴリズムを記述する必要があります。
SQLはリレーショナル・モデルだけのものではない
リレーショナル以外のデータ・モデルを扱う専用のDBMSには専用のAPIが用意されている場合があります。これが、先ほど紹介したKVSに代表されるNoSQLです。しかしここまでで説明してきたSQLの実行モデルである「SQLは入出力のインターフェースを定義しアルゴリズムはDBMSが自動生成する」という概念を超えるものが登場していないため、結局はSQLに回帰しています。最近では、NoSQLはNot Only SQL(SQLだけではない)の略であるという人もいます。
SQLはリレーショナル・モデルを操作するために考案された言語ですが、近年ではリレーショナル以外のデータ・モデルへのアクセスにも使われています。リレーショナル・モデルを扱うところから始まったOracle DatabaseやMySQLも現在ではリレーショナル以外のデータ・モデルも扱うマルチ・モデルなDBMSです。
マルチ・モデルをSQLで統一的に扱える実装を持ったDBMSは、異なる種類の問題に適合した異なる種類のデータ・モデルを同じインターフェース言語SQLでアクセスすることができます。異なるデータ・モデルのデータを結合することも容易です。
SQLは誕生から数十年が経過しており、その構文は21世紀のプログラミング言語を扱う人からすると気に入らないところがあるかもしれませんが、その実行モデルは現在においても最先端です。
まとめ
第1回はデータベースにアクセスする言語で最も使用されているSQLの実行モデルを振り返りました。インターフェースと実装を分離しアルゴリズムをDBMSに自動生成させる実行モデルの利点と、アルゴリズム探索によるレイテンシが増加する欠点をどのように回避しているかを扱いました。次回は、巨大なデータの中から条件に合致するデータの位置を短時間で特定する実装について説明したいと思います。