まず、実施例1の概要について説明する。
図1は、実施例1に係るDBMSの概要を説明する図である。
DBMS141は、クライアント通信制御部142と、クエリ実行プラン143と、クエリ実行部144と、実行タスク管理部145と、スレッド管理部146と、DBバッファ管理部147とを有する。クエリ実行部144は、クエリ実行プラン実行部151と、コンテキスト管理部152と、コンテキスト共有判定部153とを有する。
DBMS141(クエリ実行部144)は、クエリの実行において、処理ステップを実行するためのタスクを動的に生成し、動的に生成されたタスクを実行する。具体的には、例えば、DBMS141(クエリ実行部144)は、クエリの実行において、(a)処理ステップを実行するためのタスクを生成すること、(b)生成されたタスクを実行することで、前記タスクに対応した処理ステップに必要なデータを読み出すためにDBへデータ読出し要求を発行すること、(c)上記(b)で実行されたタスクに対応したN番目の処理ステップの実行結果に基づき(N+1)番目の処理ステップを実行する場合には、前記実行結果に基づくタスクを新たに生成すること(Nは1以上の整数)、及び、(d)前記新たに生成したタスクについて上記(b)及び上記(c)を行うこと、を行い、上記(b)及び(d)において、2以上の実行可能なタスクが存在する場合には、それら2以上のタスクのうちの少なくとも2つのタスクを並行して実行することができる。
DBMS141(クエリ実行部144)は、タスクを実行する際に、オペレーティングシステム(OS)が提供するスレッド(カーネルスレッド)を複数利用し、それら複数のスレッドが、それぞれ、1又は複数のプロセッサが有する1又は複数のプロセッサコアにより実行される。プロセッサコアがスレッドを実行することで、スレッドに割当たったタスクを実行する。以下、プロセッサコアがタスクを実行する、或いは、DBMS141がタスクを実行する、のような表現は、プロセッサコアがスレッドを実行することにより前記スレッドに割当たったタスクを実行することを意味する。
DBMS141は、クライアント通信制御部142を介して、クエリを受信する。クエリ実行プラン生成部143は、受信したクエリを実行するためのクエリ実行プランPLを生成する。クエリ実行プラン実行部151は、生成されたクエリ実行プランPLを実行する。スレッド管理部146は、DBMS141が構築された計算機におけるプロセッサのプロセッサコアにて実行されるスレッドを複数管理する。実行タスク管理部145は、スレッドで実行するタスクを管理する。本実施例では、実行タスク管理部145は、スレッド1つに対して、複数のタスクを割り当てることができる。これにより、スレッドの管理に要するオーバヘッドを低減することができる。
コンテキスト管理部152は、タスクを実行する際に利用するコンテキストを管理する。コンテキストとしては、複数のスレッドから利用できるように管理するスレッド間共有のコンテキストと、1つのスレッドから利用できるように管理するスレッド間非共有のコンテキストがある。スレッド間非共有のコンテキストを利用できるスレッドは、他のスレッドに比べ前記コンテキストを優先的に利用する。
図1の例では、コンテキスト#0とコンテキスト#1がスレッド間共有のコンテキストであり、コンテキスト#2、コンテキスト#3、及びコンテキスト#4がスレッド間非共有のコンテキストである。スレッド#1およびスレッド#2およびスレッド#3に割当たったタスクを実行する際に、コンテキスト#0とコンテキスト#1を利用する。スレッド#1に割当たったタスクを実行する際に、コンテキスト#2を利用する。スレッド#2に割当たったタスクを実行する際に、コンテキスト#3を利用する。コンテキスト#4は、スレッド#3に割当たったタスクを実行する際に、コンテキスト#4を利用する。
コンテキストを、スレッド間共有とするか、スレッド間非共有とするかは、コンテキスト共有判定部153による判定結果に基づいて決定する。例えば、コンテキスト共有判定部153は、クエリ実行プランの先頭の処理ステップに関わるコンテキストを、スレッド間共有のコンテキストとして良い。また、コンテキスト共有判定部153は、クエリ実行プランが並行実行可能な複数の処理ブロックにより構成されている場合には、各処理ブロックの最初の処理ステップに関わるコンテキストを、スレッド間共有のコンテキストとしても良い。また、コンテキスト共有判定部153は、1つの処理ブロックにおいて後続の処理ステップ数が所定数以上である処理ステップに関わるコンテキストを、スレッド間共有のコンテキストとして良い。処理ブロックは、1以上の処理ステップで構成されていて良い。並行実行可能な複数の処理ブロックにより構成されているクエリ実行プランの一例は、後述する。
図2は、実施例1に係るDB管理システムにおけるクエリの実行を説明する図である。なお、同図においては、上から下方向に時間の経過を表現している。
まず、スレッド管理部146が、スレッド#1、スレッド#2、スレッド#3を生成する。これらスレッド#1〜#3は、例えば、異なるプロセッサコアにより並行して実行可能である。クエリ実行プラン実行部151(具体的には、1つのプロセッサコア)が、クエリの実行を開始するコンテキスト#0を生成し、タスク#1を生成する。コンテキスト#0は、クエリ実行プランの先頭である処理ステップ#1に関するコンテキストであるのでスレッド間共有となる。クエリ実行プラン実行部151は、タスク#1をスレッド#1に割り当てる。スレッド#1は、コンテキスト#0を利用し、タスク#1を実行する。タスク#1を実行すると、コンテキスト#1を生成し、タスク#2とタスク#3を生成する。コンテキスト#1は、クエリ実行プランの先頭である処理ステップ#1に関するコンテキストであるので、スレッド間共有となる。スレッド#1は、タスク#2をスレッド#2に割り当て、タスク#3をスレッド#3に割り当てる。スレッド#2は、コンテキスト#1を利用し、タスク#2を実行する。スレッド#3は、コンテキスト#1を利用し、タスク#3を実行する。
スレッド#1がタスク#1を実行し、DBへのアクセス処理を実行する。その結果、新たなコンテキストを生成する。例えば、処理ステップ#3に関するコンテキスト#2を生成する。コンテキスト#2の処理ステップは、クエリ実行プランの先頭ではないため、スレッド間非共有となっている。すなわち、コンテキスト#2は、基本的には、スレッド#1によって利用される。スレッド#1がタスク#4を生成し、スレッド#1に割り当てる。スレッド#1は、コンテキスト#2を利用し、タスク#4を実行する。
スレッド#2がタスク#2を実行し、DBへのアクセス処理を実行する。その結果、新たなコンテキストを生成する。例えば、処理ステップ#3に関するコンテキスト#3を生成する。コンテキスト#3の処理ステップは、クエリ実行プランの先頭ではないため、スレッド間非共有となっている。すなわち、コンテキスト#3は、基本的には、スレッド#2によって利用される。スレッド#2がタスク#5とタスク#6を生成し、スレッド#2に割り当てる。スレッド#2は、コンテキスト#3を利用し、タスク#5を実行する。さらに、スレッド#2は、コンテキスト#3を利用し、タスク#6を実行する。
スレッド#3がタスク#3を実行し、DBへのアクセス処理を実行する。その結果、新たなコンテキストを生成する。例えば、処理ステップ#3に関するコンテキスト#4を生成する。コンテキスト#4の処理ステップは、クエリ実行プランの先頭ではないため、スレッド間非共有となっている。すなわち、コンテキスト#4は、基本的には、スレッド#3によって利用される。スレッド#3がタスク#7とタスク#8を生成し、スレッド#3に割り当てる。スレッド#3は、コンテキスト#4を利用し、タスク#7を実行する。さらに、スレッド#3は、コンテキスト#4を利用し、タスク#8を実行する。
このように、一つのスレッドが複数のタスクを実行し、複数の前記スレッドでクエリを実行する。その結果、複数のプロセッサコアを使い、かつ、スレッドの管理オーバヘッドが小さくなるため、クエリの実行時間が短縮できる。
以下、実施例1を詳細に説明する。
図3は、実施例1に係る計算機システムの構成図である。
計算機システムは、計算機100と、外部ストレージ装置200とを有する。計算機100と、外部ストレージ装置200とは、通信ネットワーク300を介して接続されている。通信ネットワーク300を介した通信のプロトコルとしては、例えば、FC(Fibre Channel)、SCSI(Small Computer System Interface)、IB(Infini Band)、又は、TCP/IP(Transmission Control Protocol/Internet Protocol)が採用されて良い。
計算機100は、例えば、パーソナルコンピュータ、ワークステーション又はメインフレームである。計算機100は、ネットワークアダプタ110、プロセッサ(典型的にはマイクロプロセッサ(例えばCPU(Central Processing Unit)))120、ローカル記憶デバイス130、及びメモリ140を有する。プロセッサ120は、コンピュータプログラム、例えば、図示しないOS(Operating System)や、DBMS141を実行する。1又は複数のプロセッサ120は、1又は複数のプロセッサコアを有する。各プロセッサコアがそれぞれ独立して処理を実行することができるようになっている。プロセッサコアは、メモリ140よりもアクセスレイテンシの短いキャッシュを持つ。プロセッサコアは、メモリ140に記録されたデータをキャッシュに保持し、当該データの処理を行う。一つのプロセッサコアが同じデータを連続して処理する場合は、キャッシュに保持したデータが利用できるため、別々のプロセッサコアが同じデータを連続して処理した場合に比べ処理時間は短い。本実施例では、基本的には、各プロセッサコアは、ある時点で見ると、スレッド(カーネルスレッド)を1つ実行することができる。メモリ140は、プロセッサ120によって実行されるプログラムと、プログラムが使用するデータとを一時的に記憶する。本実施例では、メモリ140は、DBの管理や関連する一連の処理を行うプログラムであるDBMS141及びデータを記憶する。メモリ141は、DBMS141にクエリを発行するためのAP(Application Program)148を記憶するようにしても良い。ローカル記憶デバイス130は、プログラム、及びプログラムが使用するデータを格納する。ネットワークアダプタ110は、通信ネットワーク300と計算機100とを接続する。また、プロセッサ120は、ネットワークアダプタ110及びメモリ140等に接続された制御デバイスに含まれている要素で良い。制御デバイスは、プロセッサ120の他に、専用ハードウェア回路(例えば、データの暗号化及び/又は復号化を行う回路)を含んで良い。
なお、計算機100は、性能面や冗長性の観点から、ネットワークアダプタ110、プロセッサ120、ローカル記憶デバイス130、及びメモリ140のうちの少なくとも1つの要素を複数備えていても良い。また、計算機100は、図示しない入力デバイス(例えば、キーボード及びポインティングデバイス)と表示デバイス(例えば液晶ディスプレイ)とを有して良い。入力デバイスと表示デバイスは一体になっていても良い。
計算機100では、DBMS141が、DBMS141に対して発行されたクエリを実行する。このクエリは、計算機100で実行されるAP148又は、通信ネットワーク300に接続された図示しない計算機(クライアント)で実行されるAPにより発行される。DBMS141は、AP148により発行されたクエリを実行し、前記クエリの実行に伴い、外部ストレージ装置200に格納されたDB206に対するI/O要求を、OSを介して外部ストレージ装置200に送信する。なお、OSは、仮想化プログラムが作成し実行する仮想マシン上で動作するOSであっても良い。
外部ストレージ装置200は、計算機100が使用するデータを記憶する。外部ストレージ装置200は、計算機100からI/O要求を受信し、I/O要求に対応した処理を実行し、処理結果を計算機100に送信する。
外部ストレージ装置200は、ネットワークアダプタ201、記憶デバイス群203及びそれらに接続されたコントローラ202を有する。
ネットワークアダプタ201は、外部ストレージ装置200を通信ネットワーク300に接続する。
記憶デバイス群203は、1つ以上の記憶デバイスを含む。記憶デバイスは、不揮発性の記憶媒体であって、例えば、磁気ディスク、フラッシュメモリ、その他半導体メモリである。記憶デバイス群203は、RAID(Redundant ARRAY of Independent Disks)に従い所定のRAIDレベルでデータを記憶するグループであっても良い。記憶デバイス群203の記憶空間に基づく論理的な記憶デバイス(論理ボリューム)が計算機100に提供されても良い。記憶デバイス群203は、DB206を記憶する。DB206は、1つ以上の表204や索引205を含む。表は1つ以上のレコードの集合であり、レコードは1つ以上のカラムから構成される。索引は、表の中の1つ以上のカラムを対象に作成されるデータ構造であり、当該索引が対象とするカラムを含む選択条件による表へのアクセスを高速化する。例えば、索引は、対象とするカラムの値毎に前記値を含む表の中のレコードを特定する情報(RowID)を保持するデータ構造であり、B木構造などが用いられる。DBの表の構成例や表同士の関連性の一例は、後述する。
コントローラ202は、例えば、メモリ及びプロセッサを含んでおり、計算機100からのI/O要求に従って、DB206を記憶した記憶デバイス群203にデータを入出力する。例えば、コントローラ202は、計算機100からの書込み要求に従う書込み対象のデータを記憶デバイス群203に格納したり、計算機100からの読出し要求に従う読出し対象のデータを記憶デバイス群203から読み出し、前記データを計算機100に送信したりする。
なお、外部ストレージ装置200は、性能面や冗長性確保の観点から、コントローラ202などの要素を複数備えても良い。また、外部ストレージ装置200を複数備えても良い。
DBMS141は、業務データを含んだDB206を管理する。DBMS141は、クライアント通信制御部142、クエリ実行プラン生成部143、クエリ実行部144、実行タスク管理部145、スレッド管理部146、及びDBバッファ管理部147を含む。
クライアント通信制御部142は、通信ネットワーク300に接続されたクライアントまたはAP148との間の通信を制御する。具体的には、クライアント通信制御部142は、クライアントまたはAP148から発行されたクエリを受信し(受け付け)、クエリの処理結果をクライアントまたはAP148に送信する処理を実行する。クエリは、例えばSQL(Structured Query Language)で記述されている。
クエリ実行プラン生成部143は、クライアント通信制御部142が受け付けたクエリを実行するために必要な1つ以上の処理ステップを有するクエリ実行プランを生成する。クエリ実行プランは、例えば、クエリの実行の際に行うべき処理ステップの実行順序を木構造で定義した情報であり、メモリ140に格納される。クエリ実行プランの一例は、後述する。
DBバッファ管理部147は、DB206内のデータを一時的に格納するための記憶領域(DBバッファ)を管理する。DBバッファは、メモリ140上に構築される。また、DBバッファは、ローカル記憶デバイス130上に構築されても良い。
クエリ実行部144は、クエリ実行プラン生成部143が生成したクエリ実行プランに従ってクエリを実行し、生成した結果をクエリの発行元に返す。クエリ実行部144は、クエリ実行プラン実行部151と、コンテキスト管理部152と、コンテキスト共有判定部153とを有する。
クエリ実行プラン実行部151は、クエリ実行プラン内の処理ステップを実行するためのタスクを動的に生成し、スレッドにタスクを割り当て、スレッドがタスクを実行することでクエリを実行する。
コンテキスト管理部152は、生成するタスクの実行に必要な情報を含むコンテキストを管理する。ここで、コンテキストは、タスクにおいて実行を開始する処理ステップが、クエリ実行プランが表す1以上の処理ステップのうちのいずれであるかを示す第1の情報と、第1の情報が示す処理ステップに要するデータのアクセス先に関する第2の情報と、タスクにより結果を生成するために必要なデータに関する第3の情報とを含む情報である。コンテキストを管理するための情報であるコンテキスト管理情報の構造については後述する。
コンテキスト共有判定部153は、コンテキストを複数のスレッド間で共有するか否かを判定する。
実行タスク管理部145は、スレッドが実行するタスクを管理する。タスクは、例えば、DBMS412で実装される疑似プロセス又は疑似スレッド(ユーザレベルスレッド)である。なお、タスクは、各処理を関数としてまとめた関数へのポインタ(関数ポインタ)の集合であってもよい。タスクを管理するための情報であるタスク管理情報の構造については、後述する。
スレッド管理部146は、クエリを実行するためのスレッドを管理する。ここで、スレッドとは、OSが提供するスレッド(カーネルスレッド)である。前述したように、プロセッサコアが割当たったスレッドを実行することにより、スレッドに割当たったタスクが実行される。なお、スレッドの代わりにプロセスを使用してもよい。
クライアント通信制御部142、クエリ実行プラン生成部143、クエリ実行部144、及びDBバッファ管理部147の少なくとも1つの処理部が行う処理の少なくとも一部が、ハードウェアで行われても良い。また、本実施例の説明において、処理部が主語になる場合は、実際には前記処理部を実行するプロセッサ120によって処理が行われるが、処理部の少なくとも一部がハードウェアで実現されている場合は、プロセッサ120に代えて又は加えて、前記ハードウェアも、主語とされ得る。DBMS141を実現するコンピュータプログラムは、プログラムソースから計算機100にインストールされて良い。プログラムソースは、例えば、計算機100が読み取り可能な記憶メディアで良いし、他の計算機でも良い。
また、図3に示したDBMS141の構成は、一例である。例えば、或る処理部が複数の処理部に分割されたり、複数の処理部の機能を統合した1つの処理部が構築されたりしても良い。
図4は、実施例1に係るDBの表及び索引の定義を説明する図である。
DB206は、表205として、例えば、カラムc1及びカラムc2を含むPart表と、カラムc3及びカラムc4を含むLineitem表とを有する。また、DB206は、索引204として、カラムc1の値に基づいたPart表に関する索引(Part索引)と、カラムc3の値に基づいたLineitem表に関する索引(Lineitem索引)とを有する。
図5は、実施例1に係るDBのPart表の一例を示す図である。
DB206のPart表は、論理的には、例えば、カラムc1の値と、対応するカラムc2の値とを対応付けた表となっている。
図6は、実施例1に係るDBのLineitem表の一例を示す図である。
DB206のLineitem表は、例えば、カラムc3の値と、対応するカラムc4の値とを対応付けた表となっている。
図7は、実施例1に係るDBにおけるpart索引及びpart表のデータ構造の一例を説明する図である。
Part索引は、例えば、カラムc1の値に基づいて、対応するカラムc2の値を格納するpart表のページ及びスロットを検索するためのB木構造となっている。ページとは、DB206に対する入出力における最小のデータ単位である。本実施例では、Part索引は、ページPを階層構造として管理している。Part索引においては、最下位のページであるリーフページと、リーフページの上位のページである上位ページとがある。ここで、上位ページの中の最上位のページをルートページということとする。
Part索引のルートページ(ページP1)には、一つ下の階層のページに対するポインタと、当該一つ下の階層のページが管理対象とするカラムc1の値の最大値とを対応付けたエントリが1以上設けられる。例えば、ページP1には、「100」以下のカラムc1の値に対する対応関係を管理するページP2へのポインタと、「100」より大きく「200」以下のカラムc1の値に対する対応関係を管理するページP3へのポインタと、「200」より大きく「300」以下のカラムc1の値に対する対応関係を管理するページP4へのポインタとが格納される。同様に、上位ページにおいては、それぞれのページの一つ下の階層のページに対するポインタと、当該1つ下の階層のページに管理されているカラムc1の値の最大値とを対応付けたエントリが1以上設けられる。
一方、リーフページには、カラムc1の値と、当該値に対応するカラムc2の値を格納するPart表における格納位置(例えば、Part表のページ番号及びの当該ページ中のスロット番号)とを対応付けたロー(行:レコード)を1以上格納する。
例えば、リーフページであるページP8には、カラムc1の値「110」に対応するカラムc2の値が格納されているページ及びスロットの番号を含むローと、カラムc1の値「130」に対応するカラムc2の値が格納されているページ及びスロットの番号を含むローとが格納される。例えば、カラムc1の値「130」に対応するカラムc2の値が格納されているページ及びスロットの番号を含むローとしては、ページP100のスロット2、ページP120のスロット1、ページP200のスロット4とを示すローが格納される。従って、カラムc1の値「130」に対応するカラムc2の値は、Part表のページP100のスロット2のレコードから「id131」となり、また、Part表のページ120のスロット1のレコードから「id132」となり、Part表のページ200のスロット4のレコードから「id133」となる。
図8は、実施例1に係るDBのクエリの一例を示す図である。
図8に示すクエリは、図4〜図7に示す構造のDB206に対するクエリの一例である。図8に示すクエリは、Part表及びLineitem表から、カラムc1の値が「130」であり、且つカラムc2の値とカラムc3の値とが同じであるものについて、カラムc1の値とカラムc4の値とを抽出することを意味している。
図9は、実施例1に係るクエリ実行プランの一例を示す図である。
同図に示すクエリ実行プランは、DBMS141が図8に示すクエリを受け付けた場合に、クエリ実行プラン生成部143により生成されるクエリ実行プランを示している。
図8に示すクエリに対応するクエリ実行プランは、図9に示すように、Part索引による索引検索を行う処理ステップ#1と、Part表からレコードを取得する処理ステップ#2と、Lineitem索引による索引検索を行う処理ステップ#3と、Lineitem表からレコードを取得する処理ステップ#4と、これらの結果をネストループ結合する処理ステップ#5とを含む。
図10は、実施例1に係るタスク管理情報のデータ構造の一例を示す図である。
タスク管理情報は、メインデータ構造体71を有する。メインデータ構造体71は、複数のスレッドを特定するスレッド特定情報(例えば、スレッド番号)と、スレッドが実行するタスクを管理するリスト管理構造体72へのポインタを、スレッドごとに対応付けて記憶する。
リスト管理構造体72は、対応するスレッドにおける実行可能なタスクを管理するための実行可能リスト72aと、対応するスレッドにおける実行待ち状態であるタスクを管理するための待ちリスト72bとを記憶する。実行可能リスト72aは、対応するスレッドにおいて実行可能なタスクに関する実行状態情報(タスク実行状態情報)73へのポインタを有する。また、タスク実行状態情報73は、対応するスレッドにおける実行可能な他のタスクに関するタスク実行状態情報73へのポインタを有する。
図10においては、例えば、スレッド#2における実行可能なタスクに関するタスク実行状態情報73としては、タスク#2に対する実行状態情報(タスク#2実行状態情報)が管理され、スレッド#2における実行待ち状態であるタスクに関するタスク実行状態情報73としては、タスク#5及びタスク#6のタスク実行状態情報73が管理されている。なお、複数のスレッド間においてタスクの偏りがある場合には、タスク(すなわち、タスク実行状態情報73)を別のスレッドのリストに移動させるようにしてもよい。
なお、本実施例では、スレッド毎に、実行可能リスト及び待ちリストを管理するようにしているが、実行可能リスト及び待ちリストを複数のスレッド間で共有しても良い。また、処理ステップごとに、実行可能リスト及び待ちリストを管理するようにしても良い。
図11は、実施例1に係るタスク実行状態情報の一例を示す図である。
タスク実行状態情報73は、ワーク領域73aと、処理ステップ73bと、処理ステップ実行状態73cとを格納する。ワーク領域73aには、ワーク領域を示すポインタが格納される。処理ステップ73bには、対応するタスクにより実行する処理ステップを識別する情報、例えば、処理ステップ番号が格納される。処理ステップ実行状態73cには、対応する処理ステップの実行状態情報(処理ステップ実行状態情報)74が格納される。処理ステップ実行状態情報74の具体例については、後述する。
図12は、実施例1に係る処理ステップ実行状態情報の第1の例を示す図である。図12は、索引検索における上位ページを使用するタスクについての処理ステップ実行状態情報を示す。
処理ステップ実行状態情報74Aは、検索条件74aと、ページ番号74bと、スロット番号74cとを含む。検索条件74aには、検索条件を格納する。同図の例では、検索条件74aには、クエリに含まれる検索条件であるkey値の範囲「115以上key以上195」を格納する。ページ番号74bには、タスクの処理で使用する上位ページの番号(ページ番号)を格納する。スロット番号74cには、タスクの処理で使用するページにおけるスロットの番号(スロット番号)を格納する。
図13は、実施例1に係る処理ステップ実行状態情報の第2の例を示す図である。図13は、索引検索におけるリーフページを使用するタスクについての処理ステップ実行状態情報を示す。
処理ステップ実行状態情報74Bは、検索条件74dと、ページ番号74eと、スロット番号74fと、処理ローID数74gとを含む。検索条件74dには、検索条件を格納する。同図の例では、検索条件74dには、検索条件であるkey値の範囲「115以上Key以上195」を格納する。ページ番号74eには、タスクの処理で使用するリーフページのページ番号を格納する。スロット番号74fには、タスクの処理で使用するページにおけるスロットのスロット番号を格納する。処理ローID番号74gには、対応するタスクで処理するスロット内のローのID番号(処理ローID番号)を格納する。
図14は、実施例1に係る処理ステップ実行状態情報の第3の例を示す図である。図14は、レコード取得を行うタスクについての処理ステップ実行状態情報を示す。
処理ステップ実行状態情報74Cは、ページ番号74hと、スロット番号74iとを含む。ページ番号74hには、タスクの処理で使用するページのページ番号を格納する。スロット番号74iには、タスクの処理で使用するページにおけるスロットのスロット番号を格納する。
図15は、実施例1に係るコンテキスト管理情報のデータ構造の一例を説明する図である。
コンテキスト管理情報80は、管理リストのメイン構造体81と、複数のコンテキスト82を含む。メイン構造体81には、コンテキスト82へのポインタを格納する。また、各コンテキスト82には、他のコンテキスト82へのポインタを格納する。本実施例では、タスクの処理でコンテキスト82を利用する場合には、タスクを実行しているスレッドが各コンテキスト82を単位として排他(ロック)をかける。ロック状態のコンテキストは他のスレッドからは利用できない。
また、コンテキスト管理情報80は、クエリを実行するスレッドに対応する検索テーブル(スレッド向け検索テーブル)83、84、85等を記憶する。スレッド#1向け検索テーブル83は、スレッド#1が利用可能なコンテキスト82へのポインタを管理する。スレッド#2向け検索テーブル84は、スレッド#2が利用可能なコンテキスト82へのポインタを管理する。スレッド#3向け検索テーブル85は、スレッド#3が利用可能なコンテキスト82へのポインタを管理する。
図16は、実施例1に係るスレッド#1向け検索テーブルの一例を示す図である。図17は、実施例1に係るスレッド#2向け検索テーブルの一例を示す図である。図18は、実施例1に係るスレッド#3向け検索テーブルの一例を示す図である。
スレッド#1向け検索テーブル83は、スレッド#1が利用可能なコンテキストへのポインタを管理するテーブルであり、各処理ステップに関わるコンテキストへのポインタをリストで管理する。図16に示すように、処理ステップ#1に関わるコンテキストへのポインタ83aと、処理ステップ#2に関わるコンテキストへのポインタ83bと、処理ステップ#3に関わるコンテキストへのポインタ83cと、処理ステップ#4に関わるコンテキストへのポインタ83dとを含む。本実施例では、ポインタ83aにはコンテキスト#1へのポインタを格納し、ポインタ83cにコンテキスト#2へのポインタを格納する。
スレッド#2向け検索テーブル84は、スレッド#2が利用可能なコンテキストへのポインタを管理するテーブルであり、各処理ステップに関わるコンテキストへのポインタをリストで管理する。図17に示すように、処理ステップ#1に関わるコンテキストへのポインタ84aと、処理ステップ#2に関わるコンテキストへのポインタ84bと、処理ステップ#3に関わるコンテキストへのポインタ84cと、処理ステップ#4に関わるコンテキストへのポインタ84dとを含む。本実施例では、ポインタ84aにコンテキスト#1へのポインタを格納し、ポインタ84cにコンテキスト#3へのポインタを格納する。
スレッド#3向け検索テーブル85は、スレッド#3が利用可能なコンテキストへのポインタを管理するテーブルであり、各処理ステップに関わるコンテキストへのポインタをリストで管理する。図18に示すように、処理ステップ#1に関わるコンテキストへのポインタ85aと、処理ステップ#2に関わるコンテキストへのポインタ85bと、処理ステップ#3に関わるコンテキストへのポインタ85cと、処理ステップ#4に関わるコンテキストへのポインタ85dとを含む。本実施例では、ポインタ85aにコンテキスト#1へのポインタを格納し、ポインタ85cにコンテキスト#4へのポインタを格納する。
スレッド#1向け検索テーブル83、スレッド#2向け検索テーブル84、及びスレッド#3向け検索テーブル85によると、コンテキスト#1は、スレッド#1、スレッド#2、又はスレッド#3において利用可能である。一方、コンテキスト#2は、スレッド#1において利用可能である。コンテキスト#3は、スレッド#2において利用可能であり、コンテキスト#4は、スレッド#3において利用可能である。ここで、コンテキスト82へのポインタが複数のスレッド向け検索テーブルに登録してある状態を、コンテキストがスレッド間共有であるといい、コンテキストへのポインタが特定の一つのスレッド向け検索テーブルに登録してある状態をコンテキストがスレッド間非共有であるという。ここで、あるスレッドを実行するプロセッサコアが当該スレッド向けのスレッド向け検索テーブルを用いて利用可能なコンテキストのことを、当該スレッドが利用可能なコンテキストという。
この状態では、コンテキスト#1はスレッド#1、スレッド#2、スレッド#3が利用し、コンテキスト#2はスレッド#1が利用し、コンテキスト#3はスレッド#2が利用し、コンテキスト#4はスレッド#3が利用する。この状態の下では、スレッド間非共有のコンテキストは一つのスレッドが連続利用するため、プロセッサコアのキャッシュによりコンテキスト利用に伴う処理の処理時間が短くできる。
なお、本実施例では、利用可能なコンテキストがスレッド間で偏った場合に、スレッドが実行するタスクの量を均等にする目的で、他のスレッド向けのスレッド向け検索テーブルを参照してもよい。具体的には、スレッドが利用可能なコンテキストがない場合、他のスレッド向けのスレッド向け検索テーブルを参照することにより、他のスレッドがスレッド間非共有のコンテキスト(コンテキスト#2、コンテキスト#3、コンテキスト#4)を利用する。例えば、スレッド#1においてスレッド#1が利用可能なコンテキストがなくなった場合、スレッド#1がスレッド#2向け検索テーブルやスレッド#3向け検索テーブルを参照し、コンテキスト#3やコンテキスト#4をスレッド#1に割当たったタスクが利用する。
図19は、実施例1に係るコンテキストの一例を示す図である。
コンテキスト82は、開始ステップ82aと、中間結果82bと、実行状態82cと、生成可能数82dとを含む。開始ステップ82aには、対応する処理ステップの番号を格納する。中間結果82bには、対応する処理ステップを実行するタスクに必要な中間結果を格納するワーク領域を示すポインタを格納する。ここで、中間結果とは、クエリの結果を生成するために必要な取得済みのデータである。実行状態82cには、対応する処理ステップにおけるタスクの実行状態、例えば、次に実行するタスクの処理の内容を特定する情報(例えば、ページ番号820、スロット番号821、及び処理ローID番号822)を格納する。ここで、ページ番号820には、次のタスクの処理で使用するリーフページのページ番号を格納する。スロット番号821には、次のタスクの処理で使用するページにおけるスロット番号を格納する。処理ローID番号822には、次のタスクの処理で使用するスロット内のローのID番号(処理ローID番号)を格納する。生成可能数82dには、対応する処理ステップにおいて、さらに生成することのできるタスクの数(タスク生成可能数)を格納する。このタスク生成可能数は、論理的に分岐する処理の数の内で、タスクとして生成されていない処理の数である。例えば、図7に示すPart索引による索引検索でキー値「130」を条件としている場合に、ページP8においては、キー値「130」に対応するエントリとしては、ローIDが3個あるので、全体として3つのローIDを用いてPart表のレコードを取得する3つのタスクを生成することができる。ここで、一つのローIDはコンテキストを生成するタスクで処理するので、生成したコンテキストから残りの2つのタスクを生成することができる。このため、タスク生成可能数は、「2」となる。
図20は、実施例1に係るクエリ受付時処理のフローチャートである。
クエリ受付時処理においては、クライアント通信制御部142が、AP148からクエリを受け付けると(ステップS1)、受け付けたクエリをクエリ実行プラン生成部143に渡し、クエリ実行プラン生成部143がクエリ実行プラン生成処理(図21参照)を実行する(ステップS2)。
クエリ実行プラン生成処理の実行後に、スレッド管理部146がスレッドを生成する(ステップS3)。ここで、生成するスレッド数は、任意の数であってよく、例えば、プロセッサ120のプロセッサコアの数と同じ数であっても良い。ここで、スレッドが動作するプロセッサコアをスレッドごとに特定のプロセッサコアに指定しても良い。すなわち、プロセッサアフィニティを設定するようにしても良い。例えば、プロセッサコアの数と同数のスレッドを生成し、各プロセッサコアでいずれか一つのスレッドが実行されるように設定しても良い。このようにすると、各スレッドによる処理の効率が良い。ここで、スレッドを生成する方法としては、OSが提供するスレッド生成のインタフェース(関数)、具体的には、pthread_create()を利用する方法がある。
次いで、クエリ実行プラン実行部151がクエリの実行を開始するコンテキストを生成し、前記コンテキストを利用して処理を行うタスクを生成し、いずれか一つのスレッドに割り当てる(ステップS4)。例えば、スレッド管理部146が最初に作成したスレッドにタスクを割り当てる。これにより、以降において、プロセッサ120のプロセッサコアがスレッドを実行し、前記スレッドに割り当てられたタスクを前記スレッドが実行する。
図21は、実施例1に係るクエリ実行プラン生成処理のフローチャートである。
クエリ実行プラン生成処理は、図20に示すクエリ受付時処理のステップS2に対応する処理である。クエリ実行プラン生成部143は、クライアント通信制御部142から渡されたクエリからクエリ実行プランを生成する(ステップS5)。例えば、図8に示すクエリを受け付けた場合には、図9に示すクエリ実行プランを生成する。次いで、クエリ実行プラン生成部143は、スレッド間共有フラグ設定処理(図22参照)を実行し(ステップS6)、クエリ実行プラン生成処理を終了する。
図22は、実施例1に係るスレッド間共有フラグ設定処理のフローチャートである。
スレッド間共有フラグ設定処理は、図21に示すクエリ実行プラン生成処理のステップS6に対応する処理である。スレッド間共有フラグ設定処理は、クエリ実行プランにおける所定の処理ステップに対して、当該処理ステップに関わるコンテキストをスレッド間共有とすべきことを示すスレッド間共有フラグを設定するための処理である。
クエリ実行プラン生成部143は、木構造となっているクエリ実行プランを辿るために、ポインタを移動させながら処理を行う。クエリ実行プランの最初の処理ステップにポインタを設定する(ステップS11)。次いで、クエリ実行プラン生成部143は、クエリ実行プランにポインタが指し示す処理ステップがあるか否かを判定する(ステップS12)。この結果、ポインタが指し示す処理ステップがない場合(ステップS12で「ない」)には、クエリ実行プランの全ての処理ステップを対象に処理をしたことを意味するので、クエリ実行プラン生成部143は、スレッド間共有フラグ設定処理を終了する。一方、クエリ実行プランの処理ステップにポインタが指し示す処理ステップがある場合(ステップS12で「ある」)には、クエリ実行プラン生成部143は、処理ステップが、処理ブロックの先頭であるか否かを判定する(ステップS13)。
ここで、処理ブロックとは、クエリ実行プランにおける逐次的に実行しなければならない1つ以上の処理ステップを、並行して実行できる集合に区分した場合における当該集合のことをいう。例えば、図9に示すクエリ実行プランには、1つの処理ブロックが含まれる。ここで、処理ブロックについて、他のクエリ実行プランを用いて説明する。
図23は、実施例1に係るクエリ実行プランの他の例を説明する図である。
図23に示すクエリ実行プランは、Part索引による索引検索を行う処理ステップ#1と、Part表からレコードを取得する処理ステップ#2と、Lineitem表に対してテーブルスキャンを実行する処理ステップ#3と、処理ステップ#2及び処理ステップ#3の結果をハッシュ結合する処理ステップ#4とを有する。ここで、処理ステップ#1及び処理ステップ#2と、処理ステップ#3とは並行して実行可能な処理である。このクエリ実行プランは、処理ステップ#1及び処理ステップ#2が含まれる処理ブロック#1と、処理ステップ#3及び処理ステップ#4が含まれる処理ブロック#2とを含む。このクエリ実行プランにおいては、処理ステップ#1と、処理ステップ#3とが処理ブロックの先頭の処理ステップである。
なお、このようなクエリ実行プランの他に、例えば、副問合せや、導出表が含まれるクエリに対応するクエリ実行プランにおいても、複数の処理ブロックが含まれる。
図22の説明に戻り、ステップS13の結果、処理ステップが処理ブロックの先頭である場合(ステップS13で「はい」)には、クエリ実行プラン生成部143は、当該処理ステップに対して、スレッド間共有フラグを設定する(ステップS14)。例えば、図9に示すクエリ実行プランでは、処理ステップ#1にスレッド間共有フラグを設定する。図23に示すクエリ実行プランでは、処理ステップ#1と処理ステップ#3にスレッド間共有フラグを設定する。そして、処理をステップS15に進める。ここで、処理ステップが処理ブロックの先頭である場合においてコンテキストを複数のスレッドで共有すべきとするのは、処理ブロックの早い段階において、起点となるタスクを複数のスレッドに分散させるためである。
一方、ステップS13の結果、処理ステップが処理ブロックの先頭でない場合(ステップS13で「いいえ」)には、クエリ実行プラン生成部143は、処理をステップS15に進める。
ステップS15では、クエリ実行プラン生成部143が次の処理ステップにポインタを移動させ、処理をステップS12に進む。
なお、図22に示すスレッド間共有フラグ設定処理においては、処理ブロックの先頭の処理ステップについて、スレッド間共有フラグを設定するようにしていたが、例えば、処理ブロックにおける後続の処理ステップの数が所定数以上ある処理ステップについて、スレッド間共有フラグを設定するようにしても良い。
図24は、実施例1に係る結果送信処理のフローチャートである。
結果送信処理は、クライアント通信制御部142がクエリを受け付けた後に、クライアント通信制御部142により開始される。クライアント通信制御部142は、クエリ実行部144における受け付けたクエリの結果の有無を確認する(ステップS21)。
この結果、クエリの結果がある場合(ステップS21で「有」)には、クライアント通信制御部142は、クエリ実行部144からクエリの結果を取得し(ステップS22)、クエリの発行元であるAP148に対してクエリの結果を送信する(ステップS26)。
一方、クエリの結果がない場合(ステップS21で「無」)には、クライアント通信制御部142は、クエリ実行部144のクエリ終了フラグがクエリの終了を示す「終了」であるか、クエリが終了していないことを示す「未終了」であるかを判定する(ステップS23)。この結果、クエリ終了フラグが「終了」である場合(ステップS23で「終了」)には、結果にNOROW(該当レコードなし)を設定し(ステップS24)、クエリの発行元であるAP148に対してクエリの結果を送信する(ステップS26)。
一方、クエリ実行部144のクエリ終了フラグがクエリの未終了を示す「未終了」である場合(ステップS23で「未終了」)には、クライアント通信制御部142は、クエリ実行部144が結果を生成するのを所定時間待って(ステップS25)、処理をステップS21に進める。
図25は、実施例1に係るスレッド実行処理のフローチャートである。
スレッド実行処理は、プロセッサ120のプロセッサコアが、図20のステップS3において生成されたスレッドを実行することにより実現される。なお、複数のスレッドが存在する場合には、別のプロセッサコアが別のスレッドに対するスレッド実行処理を並行して行うことができる。
プロセッサコアは、対応するスレッドにおいて実行するタスクを選択する(ステップS31)。具体的には、プロセッサコアは、実行タスク管理部145が管理するタスク管理情報の対応するスレッドの実行可能リストに含まれるタスクを選択する。
次いで、プロセッサコアは、実行するタスクの有無を判定し(ステップS32)、実行するタスクがない場合(ステップS32で「無」)には、処理をステップS34に進める一方、実行するタスクがある場合(ステップS32で「有」)には、タスクの開始又はタスクの再開を行う(ステップS33)。具体的には次の処理を行う。プロセッサコアは、実行可能リストに含まれるタスクの一つを選ぶ。プロセッサコアは、選んだタスクのタスク実行状態情報を確認し、タスクの開始またはタスクの再開を行う。タスク実行状態情報の処理ステップが設定していない場合はタスクの処理を開始する。具体的には、タスク実行処理(図26参照)を実行する。タスク実行状態情報の処理ステップが設定してある場合はタスクの処理を再開する。具体的には、タスクの中断した処理から実行を再開する。本実施例では、図29のステップS66からの処理から再開する。なお、タスクの実行が終了した後、又はタスクの実行が待ち状態となった後、プロセッサコアは、処理をステップS31に進める。
ステップS34では、プロセッサコアは、他のスレッドの有無を確認し(ステップS34)、他のスレッドがない場合(ステップS34で「無」)には、クエリ実行部144のクエリ終了フラグに終了を設定し(ステップS35)、スレッド実行処理を終了する。これにより、当該スレッドが消滅することとなる。一方、他のスレッドがある場合(ステップS34で「有」)には、プロセッサコアは、スレッド実行処理を終了する。これにより、当該スレッドが消滅することとなる。
図26は、実施例1に係るタスク実行処理のフローチャートである。
タスク実行処理は、図25のステップS33において、タスクの処理を開始する場合における処理に対応する。このタスク実行処理は、プロセッサコアがスレッドにおけるタスクを実行することにより実現される。
プロセッサコアは、コンテキスト検索処理(図27参照)を実行し(ステップS36)、コンテキスト検索処理により検索されたコンテキストの有無を確認する(ステップS37)。この結果、コンテキストがない場合(ステップS37で「なし」)には、実行すべきDBへのオペレーションがないことを意味するので、タスク実行処理を終了する。
一方、コンテキストがある場合(ステップS37で「あり」)には、プロセッサコアは、当該タスクのタスク実行状態情報73(図11参照)を設定する(ステップS38)。具体的には、プロセッサコアは、検索されたコンテキスト82の開始ステップ82aの値を、タスク実行状態情報73の処理ステップ73bにコピーする。コンテキストの中間結果82bのポインタが示すワーク領域のデータを、タスク実行状態情報73のワーク領域73aのポインタが示すワーク領域にコピーする。さらに、プロセッサコアは、コンテキスト82の実行状態82cの値を、タスク実行状態情報73の処理ステップ実行状態73cにコピーする。例えば、図19に示すコンテキスト82である場合には、タスク実行状態情報73の処理ステップ実行状態73cには、ページ番号として、コンテキスト82のページ番号820の値「8」が格納され、スロット番号として、コンテキスト82のスロット番号821の値「2」が格納され、処理ローID番号として、コンテキスト82の処理ローID番号822の値「2」が格納される。この後、プロセッサコアは、コンテキスト82の実行状態82cを次のタスクにおける処理内容に対応するように更新する。例えば、図19に示すコンテキスト82においては、処理ローID番号822の値を1つ進めて「3」とする。
このように設定された図19に示すタスク実行状態情報73によると、当該タスクの処理で、ページ番号「8」のページ(図7のページP8)のスロット番号「2」の処理ローID番号「2」のローIDを参照していることを意味している。この結果、このタスクは、以降の処理において、該当するローIDが示すページ「P120」のスロット番号「1」に格納されているレコード(id132を持つレコード)を参照することから処理を開始することとなる。
ステップS38の後に、プロセッサコアは、クエリ実行プラン実行処理(図28参照)を実行する。タスクの処理が終了した場合にステップ39が終了し、処理をステップS36に進める。
図27は、実施例1に係るコンテキスト検索処理のフローチャートである。
コンテキスト検索処理は、図26のステップS36に対応する処理である。プロセッサコアは、実行しているスレッド(自スレッド)向けのスレッド向け検索テーブル(83、84、又は85)のポインタを用いて、コンテキストを探す(ステップS41)。本実施例では、プロセッサコアは、最後の処理ステップから最初の処理ステップの順にコンテキストを探す。次いで、プロセッサコアは、探索できたコンテキストの有無を確認する(ステップS42)。この結果、コンテキストが見つかった場合(ステップS42で「有」)には、コンテキスト検索処理を終了する。一方、コンテキストがない場合(ステップS42で「無」)には、利用可能なコンテキストの数がスレッド間で偏っている可能性があることを意味しているので、自スレッド以外のスレッド(他スレッド)向けのスレッド向け検索テーブルのポインタを用いて、コンテキストを探す(ステップS43)。本実施例では、他スレッド向けのスレッド向け検索テーブルからコンテキストを取得する場合には、プロセッサコアは、最初の処理ステップから最後の処理ステップの順にコンテキストを探す。ここで、最初の処理ステップからコンテキストを探すのは、最初の処理ステップに近いものほど、生成するタスク数が多くなる可能性が高いので、早い段階で各スレッドに負荷を分散することができるためである。ステップS43の後、プロセッサコアは、コンテキスト検索処理を終了する。
例えば、スレッド#1でコンテキスト検索処理を実行している場合は、スレッド#1はスレッド#1向け検索テーブルでコンテキストを探す。スレッド#1は、スレッド#1向け検索テーブルでは処理ステップ#4から処理ステップ#1の順に探す。図16の状態では、スレッド#1はコンテキスト#2へのポインタを見つけ、コンテキスト#2を利用する。コンテキスト#2がなくなった場合、コンテキスト#1へのポインタを見つけ、コンテキスト#1を利用する。さらに、コンテキスト#1がなくなった場合、スレッド#1向け検索テーブルには利用可能なコンテキストがない状態となり、スレッド#1は自スレッド以外のスレッド向けの検索テーブルでコンテキストを探す。この場合、処理ステップ#1から処理ステップ#4の順に探す。スレッド#1は、スレッド#2向け検索テーブルの処理ステップ#1、スレッド#3向け検索テーブルの処理ステップ#1、スレッド#2向け検索テーブルの処理ステップ#2、スレッド#3向け検索テーブルの処理ステップ#2、スレッド#2向け検索テーブルの処理ステップ#3、スレッド#3向け検索テーブルの処理ステップ#3、スレッド#2向け検索テーブルの処理ステップ#4、スレッド#3向け検索テーブルの処理ステップ#4の順に探す。図17と図18でコンテキスト#1へのポインタがなくなっている場合は、スレッド#1はスレッド#2向け検索テーブルでコンテキスト#3へのポインタを見つけ、コンテキスト#3を利用する。
上記コンテキスト検索処理においては、コンテキストがない場合、すなわち、コンテキストが0の場合、他スレッド向けのスレッド向け検索テーブルを参照して、コンテキストを探すようにしていたが、例えば、コンテキストが所定数以下である場合に、他スレッド向けのスレッド向け検索テーブルを参照して、コンテキストを探すようにしてもよい。
また、上記コンテキスト検索処理のステップS43によると、各スレッド間の利用可能なコンテキストの数に基づいて、スレッド間の負荷の偏りを低減することができるが、この処理以外に、後述する変形例(図34参照)に示す負荷分散スレッドにより調整するようにしてもよい。
図28は、実施例1に係るクエリ実行プラン実行処理のフローチャートである。
クエリ実行プラン実行処理は、図26のステップS39に対応する。このクエリ実行プラン実行処理は、プロセッサコアがスレッドに割当たったタスクを実行することにより実現される。なお、このクエリ実行プラン実行処理を実行する論理的な機能部が、クエリ実行プラン実行部151に相当する。
プロセッサコアは、DBページ取得処理(図29参照)を実行する(ステップS51)ことにより、DB206におけるページを取得する。次いで、プロセッサコアは、ページにおけるデータについて検索条件と合致するものがあるかの真偽を判定する(ステップS52)。例えば、索引の上位ページであれば、上位ページ内の検索処理であり、リーフページであればリーフページの検索処理である。この結果、ページにおけるデータに、検索条件と合致するデータがない場合(ステップS52で「偽」)には、プロセッサは、クエリ実行プラン実行処理を終了する。
一方、検索条件に合致するデータがある場合(ステップS52で「真」)には、プロセッサコアは、検索条件に合致するデータが1つであるか、2つ以上であるかを判定する(ステップS53)。この結果、検索条件に合致するデータが1つである場合(ステップS53で「1つ」)には、プロセッサコアは、処理をステップS55に進める。一方、検索条件に合致するデータが2つ以上である場合(ステップs53で「2つ以上」)には、プロセッサコアは、新規タスク追加処理(図30参照)を実行し(ステップS54)、処理をステップS55に進める。
ステップS55では、プロセッサコアは、当該タスクによる処理ステップにおけるDBのページに対する処理を実行する。ここで、DBのページに対する処理とは、例えば、索引の上位ページであれば検索条件に合致するページ番号を読み出す処理であり、リーフページであれば検索条件に合致するローIDを読み出す処理であり、表のページであればレコードのカラムを読み出す処理である。
次いで、プロセッサコアは、次のDBのページと、当該DBページに対する処理を決定し(ステップS56)、ステップS57に処理を進める。
ステップS57では、プロセッサコアは、取得しているDBページを開放する。次いで、ステップS58では、プロセッサコアは、次の処理があるか否かを判定する。具体的には、現在行っている処理ステップが完了しており、当該処理ステップを含む処理ブロックにおいて次の処理ステップがない場合に「無」と判定する。この結果、次の処理がある場合(ステップS58で「有」)には、プロセッサコアは、処理をステップS51に進める一方、次の処理がない場合(ステップS58で「無」)には、処理結果をクエリ実行部144に渡し(ステップS59)、クエリ実行プラン実行処理を終了する。
ここで、次のDBページと、当該DBページに対する処理の決定について、図4〜図7に示すDB206に対して、c1=130を検索条件として、Part索引を索引検索する場合を例に説明する。
最初に索引検索を開始している場合においては、プロセッサコアは、索引のルートページ(ページ番号「P1」のページ)を次のDBページと決定し、当該ページに対して「130」というキーを探す上位ページ内の検索処理をDBページに対する処理として決定し、処理を開始する。ステップS51で、プロセッサコアはページP1を読み込み、ステップS52で当該ページP1の中でc1「130」を含むエントリを探す。c1「200」を含むエントリを1つ見つけるので、ステップS55とステップ56で、次の処理としてページP3に対して上位ページ内の検索処理をDBページに対する処理と決定する。また、ステップ51からステップS55で、ページP3に対する処理を行う。プロセッサコアは、ページP3を読み込み、当該ページP3でc1「130」を含むエントリを探し、c1「130」を含むエントリにおいてページP8へのポインタを見つける。この結果、ページP8を次のDBページと決定し、当該ページP8に対してリーフページ内の検索処理をDBページに対する処理と決定する。
プロセッサコアは、ステップ51からステップS53で、ページP8を読み込み、当該ページP8でc1「130」を含むエントリを探し、Part表のページ「P100」と、スロット番号「2」を見つける。ここで条件に合致するデータが3つあるので、当該タスクで処理するデータ以外の2つのデータの処理を行うために、新規タスク追加処理(ステップ54)を行う。本実施例では、当該タスクで処理するデータを最初のデータとし、ステップ56でPart表のページP100を次のDBページと決定し、当該ページP100に対してスロット番号2にあるレコードを取得する処理をDBページに対する処理と決定する。
図29は、実施例1に係るDBページ取得処理のフローチャートである。
DBページ取得処理は、クエリ実行プラン実行処理(図28)のステップS51に対応する。このDBページ取得処理は、プロセッサコアがスレッドに割当たったタスクを実行することにより実現される。
プロセッサコアは、DBバッファ管理部147において、取得対象のDBページに対応するバッファページ(DBバッファページ)を検索し(ステップS61)、対応するDBバッファページの有無を確認する(ステップS62)。
この結果、対応するDBバッファページがある場合(ステップS62で「有」)には、プロセッサコアは、DB206からの当該ページの読込みが完了しているか否かを判定し(ステップS63)、読み込みが完了している場合(ステップS63で「完了」)には、DBページ取得処理を終了する一方、読み込みが完了していない場合(ステップS63で「未完」)には、ステップS66に処理を進める。
一方、対応するDBバッファページがない場合(ステップS62で「無」)には、プロセッサコアは、DBバッファ管理部147から空きDBバッファページを取得し(ステップS64)、DB206に対して対応するページを空きDBバッファページに読込むためのDBページ読込み要求を発行し(ステップS65)、処理をステップS66に進める。
ステップS66では、プロセッサコアは、ページの読込みが完了するのを待つ。ここで、プロセッサコアは、ページの読込みが完了するまで待つ方式、すなわち、同期I/Oを採用せずに、ページの読込みが完了していなくて他の処理を実行する方式、すなわち、非同期I/Oを採用しても良い。例えば、プロセッサコアは、実行中のタスクの処理を中断して待ち状態とし、タスク実行状態情報を待ちリストにつけかえる。そして、別のスレッド(又は、別タスク)により対応するページの読込みの完了を確認する。そして、当該別のスレッド(別のスレッドを実行するプロセッサコア)がページの読込みの完了を確認した場合には、当該タスクのタスク実行状態情報を実行可能リストにつけかえ、当該タスクの処理を再開させるようにしてもよい。このように、非同期I/Oを採用すると、プロセッサコアは、ページの読込み完了を待たずに、他のタスクの実行を行うことができるようになり、DBMS141における処理効率を向上することができる。なお、読み込みが完了した場合には、プロセッサコアは、DBページ取得処理を終了する。
図30は、実施例1に係る新規タスク追加処理のフローチャートである。
新規タスク追加処理は、クエリ実行プラン実行処理(図28)のステップS54に対応する。この新規タスク追加処理は、ステップS53で条件に合致するデータが2以上ある場合に、合致するデータ中の1つのデータ(例えば、最初のデータ)以外のデータを対象にして実行される。
プロセッサコアは、処理対象のデータに基づいて、コンテキスト82を作成する(ステップS71)。次いで、プロセッサコアは、作成したコンテキスト82をスレッド間で共有するか否かを判定するためのコンテキスト共有判定処理(図31参照)を実行する(ステップS72)。次いで、プロセッサコアは、作成したコンテキスト82をコンテキスト管理情報80に登録するコンテキスト登録処理(図32参照)を実行する(ステップS73)。
次いで、プロセッサコアは、新たなタスクを生成することが可能であるか否かを判定する(ステップS74)。新たなタスクを生成することが可能であるか否かは、例えば、DBMS141において生成されているタスクの数が、生成可能なタスクの数の上限値に達しているか否かを判定することにより判定できる。
この結果、タスクを生成可能である場合(ステップS74で「可」)には、プロセッサコアは、新たなタスクを生成するためのタスク生成処理(図33参照)を実行し(ステップS75)、新規タスク追加処理を終了する。一方、タスクを生成可能でない場合(ステップS74で「否」)には、タスクを生成することなく新規タスク追加処理を終了する。
図31は、実施例1に係るコンテキスト共有判定処理のフローチャートである。
コンテキスト共有判定処理は、新規タスク追加処理(図30)のステップS72に対応する。このコンテキスト共有判定処理は、プロセッサコアがスレッドに割当たったタスクを実行することにより実現される。
プロセッサコアは、生成したコンテキストに関する処理ステップのスレッド間共有フラグを参照する(ステップS81)。その結果、処理ステップにスレッド間共有フラグが設定されている場合(ステップS81で「フラグ設定あり」)には、プロセッサコアは、当該コンテキストを複数のスレッドから利用可能とするスレッド間共有と判断し(ステップS82)、コンテキスト共有判定処理を終了する。一方、処理ステップにスレッド間共有フラグが設定されていない場合(ステップS81で「フラグ設定なし」)には、プロセッサコアは、当該コンテキストを一つのスレッドにより利用可能とするスレッド間非共有と判断し(ステップS83)、コンテキスト共有判定処理を終了する。
なお、コンテキスト共有判定処理は、スレッド間共有フラグに基づいて、生成するコンテキストをスレッド間共有するかしないかを判定していたが、これに限られない。例えば、プロセッサコアが、DBMS141の実行状態に基づいて、生成するコンテキストをスレッド間共有するかしないかを判定するようにしてもよい。
例えば、DBMS141の実行状態として、DBMS141の現存のタスク数を採用する。プロセッサコアは、現存のタスク数が所定数以下である場合には、生成するコンテキストをスレッド間共有と判定し、現存のタスク数が所定数以下でない場合には、生成するコンテキストをスレッド間非共有と判定しても良い。
また、DBMSの実行状態として、コンテキストに含まれる中間結果82bを採用し、プロセッサコアは、前記コンテキストに含まれる中間結果82bのデータ量が所定量以下である場合には、生成するコンテキストをスレッド間共有すると判定し、前記コンテキストに含まれる中間結果82bのデータ量が所定量以下でない場合には、生成するコンテキストをスレッド間非共有と判定しても良い。
図32は、実施例1に係るコンテキスト登録処理のフローチャートである。
コンテキスト登録処理は、新規タスク追加処理(図30)のステップS73に対応する。このコンテキスト登録処理は、プロセッサコアがスレッドに割当たったタスクを実行することにより実現される。
プロセッサコアは、作成されたコンテキストをコンテキスト管理情報80の管理リストに登録する(ステップS91)。具体的には、プロセッサコアは、管理リストに接続された最後のコンテキストの後ろに作成されたコンテキストを接続する。
次いで、プロセッサコアは、コンテキスト共有判定処理(図31参照)の結果を確認する(ステップS92)。この結果がスレッド間共有である場合(ステップS92で「共有」)には、複数のスレッド向け検索テーブルに、作成されたコンテキストへのポインタを登録し、コンテキスト登録処理を終了する。本実施例では、DBアクセス処理を実行する全てのスレッド向け検索テーブルにコンテキストへのポインタを登録する(ステップS93)。この他に、特定のスレッド向け検索テーブルにコンテキストへのポインタを登録してもよい。
特定のスレッド向け検索テーブルにコンテキストへのポインタを登録するケースを説明する。例えば、計算機のハードウェア構成情報に基づき、登録するスレッド向け検索テーブルを特定する。ハードウェア構成情報には、プロセッサ構成やキャッシュ構成やメモリ構成が考えられる。例えば、一つのプロセッサにある複数のプロセッサコアが実行している複数のスレッドにおいて、利用可能なコンテキストのタスク生成可能数の総和が最も少ない前記複数のスレッドに対応するスレッド向けのスレッド向け管理テーブルに登録する。本実施例において、スレッド#2を実行しているプロセッサコアとスレッド#3を実行しているプロセッサコアが同じプロセッサであり、前記プロセッサはスレッド#1を実行しているプロセッサと異なり、コンテキスト#1へのポインタがスレッド#2のスレッド向け検索テーブルとスレッド#3のスレッド向け検索テーブルに登録されている状況を考える。処理ステップ#1に対する新しいコンテキスト#4が生成された場合には、コンテキストが少ないプロセッサのプロセッサコアが実行しているスレッドスレッド向け検索テーブルに登録する。このケースでは、スレッド#1のスレッド向け検索テーブルに登録する。この例では、1つのスレッド向け検索テーブルに登録したが、スレッド#1を実行するプロセッサコアのプロセッサが他にDBアクセス処理を実行するスレッドを実行している場合は、複数のスレッド向け検索テーブルに登録することになる。
このほか、コンテキストを生成したプロセッサコアを含むプロセッサに対応する複数のスレッドに対応するスレッド向けのスレッド向け管理テーブルに登録してもよい。また、一つのプロセッサにある複数のプロセッサコアが実行している複数のスレッドにおいて、利用可能なコンテキストの総数が少ない前記複数のスレッドに対応するスレッド向けのスレッド向け管理テーブルに登録してもよい。また、プロセッサ内でキャッシュを共有しているプロセッサコアが実行している複数のスレッドのスレッド向け管理テーブルに登録してもよい。また、コンテキストを記録するメモリに近いプロセッサコアが実行している複数のスレッドのスレッド向け管理テーブルに登録してもよい。また、コンテキストを利用する際に参照するDBバッファページが記録されているメモリに近いプロセッサコアが実行している複数のスレッドのスレッド向け管理テーブルに登録してもよい。
一方、この結果がスレッド間非共有である場合(ステップS92で「非共有」)には、プロセッサコアは、1つのスレッド向け検索テーブルにポインタを登録し、コンテキスト登録処理を終了する。本実施例では、自身が実行しているスレッド(自スレッド)向けのスレッド向け検索テーブルに、作成されたコンテキストへのポインタを登録し(ステップS94)、コンテキスト登録処理を終了する。このほかに、利用可能なコンテキストが最も少ないスレッド向け検索テーブルに登録してもよく、また、利用可能なコンテキストのタスク生成可能数の総和が最も少ないスレッド向け検索テーブルに登録してもよい。
図33は、実施例1に係るタスク生成処理のフローチャートである。
タスク生成処理は、新規タスク追加処理(図30)のステップS75に対応する。このタスク生成処理は、プロセッサコアがスレッドに割当たったタスクを実行することにより実現される。
次いで、プロセッサコアは、コンテキスト共有判定処理(図31参照)の結果を確認する(ステップS101)。この結果がスレッド間共有である場合(ステップS101で「スレッド間共有」)には、プロセッサコアは、タスクを生成し、コンテキストのポインタを登録したスレッド向け検索テーブルに対応する2つ以上のスレッドにタスクを割り当てる(ステップS102)。生成するタスクの合計はコンテキストの生成可能数を上限とする。各スレッドに割り当てるタスクの数は、コンテキストの生成可能数をスレッド数で割った数とする。その後、プロセッサコアは、タスク生成処理を終了する。
一方、この結果がスレッド間非共有である場合(ステップS101で「スレッド間非共有」)には、プロセッサコアは、タスクを生成し、コンテキストのポインタを登録したスレッド向け検索テーブルに対応する1つのスレッドにタスクを割り当てる(ステップS103)。生成するタスクの数はコンテキストの生成可能数を上限とする。ここで、タスクを割り当てるスレッドとしては、プロセッサコアが実行している自スレッドであっても良く、自スレッド以外のスレッドであっても良い。ステップS103の後、プロセッサコアは、タスク生成処理を終了する。
次に、本実施例の変形例について説明する。
上記実施例において、クエリ実行部144が以下に示す負荷分散処理を実行するようにしてもよい。
図34は、変形例に係る負荷分散処理のフローチャートである。
負荷分散処理は、クエリ実行部144により実行されるが、具体的には、プロセッサコアが、DB処理を行うためのスレッド以外のスレッド(負荷分散スレッド)を実行することにより実現することができる。この負荷分散処理は、クライアント通信制御部142がクエリを受け付けた後に開始される。
プロセッサコアは、クエリ処理が終了したか否かを判定し(ステップS111)、クエリ処理が終了した場合(ステップS111で「終了」)には、負荷分散処理を終了する。
一方、クエリ処理が終了していない場合(ステップS111で「未終了」)には、プロセッサコアは、各スレッド向け検索テーブルから利用可能なコンテキストにおけるタスク生成可能数の総和を計算する(ステップS112)。
次いで、プロセッサコアは、各スレッドが生成可能なタスク生成可能数の総和に偏りがあるか否かを判定する(ステップS113)。ここで、プロセッサコアは、例えば、タスク生成可能数が所定数(例えば、0)以下である場合に偏りがあると判定しても良い。
この結果、各スレッドが生成可能なタスク生成可能数の総和に偏りがない場合(ステップS113で「無」)には、処理をステップS115に進める。
一方、各スレッドで生成可能なタスク生成可能数の総和に偏りがある場合(ステップS113で「有」)には、プロセッサコアは、コンテキストの位置を変更、すなわち、コンテキストを参照するポインタが格納されるスレッド向け検索テーブルを別のスレッド向け検索テーブルに変更することにより、各スレッドで生成可能なタスク生成可能数の総和の偏りを減らすようにする。具体的には、タスク生成可能数の総和が最大のスレッド向けのスレッド向け検索テーブルにより利用可能なコンテキストのポインタを、タスク生成可能数の総和が少ないスレッド向けのスレッド向け検索テーブルに登録する。この後、プロセッサコアは、処理をステップS115に進める。
ステップS115では、プロセッサコアは、当該負荷分散処理を所定時間スリープし、処理をステップS111に進める。
この負荷分散処理により、各スレッドに対する負荷を適切に分散させることができる。
なお、上記負荷分散処理では、各スレッドで生成可能なタスク生成可能数の総和の偏りに基づいて、コンテキストを利用するスレッドの変更を行うようにしていたが、タスク生成可能数の総和の偏りと異なる、スレッドに関わる実行状態に基づいて、スレッドの負荷を把握し、コンテキストを利用するスレッドを変更するようにしてもよい。例えば、各スレッドにおけるコスト計算を行い、前記コストに基づいて、コンテキストを利用するスレッドを変更するようにしても良い。コスト計算の例として次のような値が考えられる。コンテキスのコストを当該コンテキストから処理する処理ステップ数と生成可能数の積とし、当該スレッドから利用可能なコンテキストのコストの総和を当該スレッドのコストとする。
なお、上記負荷分散処理は、DB処理を行うためのスレッドが実行してもよい。例えば、スレッドの終了時(ステップS32の「無」と判定した場合)や、タスクの終了時(ステップS37で「なし」と判定した場合)に実行してもよい。この場合、負荷分散処理は、ステップS112からステップS114までを実行する。