Coherence問合せ言語、TRACE、EXPLAIN PLAN

概要

    目的

    Coherence 3.6より以前のバージョンでは、開発者はキャッシュに対する問合せを実行するために、フィルタリング・メカニズムを使用する必要がありました。このメカニズムは簡潔で効率的ではありますが、正しくコーディングを行うために開発者にかなりの努力が求められました。Coherence 3.6ではCoherence問合せ言語(CohQL)という、キャッシュに対してSELECTタイプの演算を実行するためのSQLに似た軽量の言語が導入されました。また、Coherence 3.7では、SELECT演算をサポートする、パフォーマンス面を重視した追加機能が導入されました。このチュートリアルの目的は、以下の機能について確認し、演習を行うことです。

    • フィルタ - 特定の基準に基づいてキャッシュから特定のデータセットを選択する方法
    • Coherence問合せ言語 - SELECTタイプの構文を使用するためにフィルタを簡素化する方法
    • EXPLAIN PLAN - フィルタまたはSELECTのコストを見積もる方法
    • TRACE - フィルタまたはSELECTの実際のコストを評価する方法

    所要時間

    約45分

    はじめに

    Coherence問合せ言語(CohQL)を使用すると、開発者はキャッシュ・データに対するSQLに似た複雑な問合せを作成できます。 問合せは以下のいずれかの方法で実行します。

    • フィルタの使用 - フィルタ(com.tangosol.util.Filterクラスに基づくフィルタ)を使用すると、値のエクストラクタと、andornot、likeなどのフィルタを組み合わせて問合せを開発し、問合せを実行できます。 この後、フィルタをキャッシュに対して実行すると、結果セットが返されます。
    • 問合せの使用 - 問合せではSQLに似た構文とcom.tangosol.util.QueryHelperクラスのインポートを使用して、Filterインスタンスを作成します。 内部的に、QueryHelperでFilterのセットが作成され、提供されたSELECT文とのマッチングがこのFilterで実行されます。

    次にフィルタがキャッシュに対して実行されます。キャッシュではクラスタの各メンバーに対して演算が実行され、集約後の結果が返されます。 フィルタのパフォーマンスは、索引をよく検討して使用することで改善できます。 索引は、関連するすべてのデータベースに対して同じ関数を提供するものであり、その結果、Coherenceでより速くデータを返すことができます。ただし、索引を常に最新状態に保つためのメモリと処理能力が必要になるというコストが伴います。また、索引は、データ抽出のためにエンティティ・オブジェクトに直接依存しています。 エンティティでは、データの抽出を効率的に行える場合とそうではない場合があります。そのため、索引を最新状態に保つコストが、問合せによって短縮できる時間に見合わない場合があります。これらは、エンティティ・フィールドに索引を適用する理由、あるいは適用しない理由に関する数少ない検討事項です。

    Coherence 3.7.1より前のバージョンでは、問合せにかかる時間をコード内か手動で測定する以外に、問合せのパフォーマンスを計測する方法はありませんでした。このどちらの方法も最適ではなく、使いやすくもありませんでした。さらに、問合せのどの部分がもっとも影響度が高いのかを見つけ出すことも不可能でした。 たとえば、特定のandフィルタの方が、likeフィルタよりも問合せのパフォーマンスに対する影響度が高いのか、 あるいは、いずれかのフィールドに索引を設定するとパフォーマンスが変化するのか、などの情報が分かりませんでした。

    Coherence 3.7.1では、問合せのパフォーマンスの静的評価および動的評価をサポートする2つの機能が導入されました。これらの2つの機能はそれぞれ以下のとおりです。

    • EXPLAIN PLAN - 問合せの静的分析であり、問合せの見積もりコストを生成する
    • TRACE - 問合せの動的分析であり、問合せの実際の有効性の評価を生成する

    EXPLAIN PLAN文とTRACE文を使用すると、開発者は問合せの実行方法、句の実行順、特定の索引の有効性について検証できます。これらの両方の機能を、コマンドラインから、またはアプリケーション・コード内部から実行できます。 特定の問合せのパフォーマンスを検証するための、使いやすく堅牢なメカニズムが提供されます。

    このチュートリアルの目的は以下のとおりです。

    • 基本的なFilterクラスとQueryHelperクラスを使用してキャッシュの問合せを行う
    • EXPLAIN PLANを使用して問合せのパフォーマンスを見積もる
    • 問合せのパフォーマンスとフィルタの影響度を評価する
    • Coherence問合せアプリケーションを使用して問合せ方法を確認する

    ハードウェアとソフトウェアの要件

    ハードウェアとソフトウェアの要件のリストは、以下のとおりです。

    • Coherence 3.7.1。こちらからダウンロードできます。
    • Coherence CQLサンプル・コード。こちらからダウンロードできます。

    前提条件

    このチュートリアルを始める前に以下のことを確認してください。

    • Linuxのコマンドおよびコマンドライン構文に関する実用的な基本知識を有していること。
    • Coherence 3.7.1にアクセスできるか、またはインストール済みであること。
    • OBEサンプル・コードをダウンロードし、解凍していること。 このコードは、LinuxやLinuxに類似したオペレーティング・システムで実行することを目的としたものですが、必要であればWindows用に変更することも可能です。
    • Oracle Java JDKバージョン1.6.0_26以降をダウンロードし、インストールしていること。 Oracle JDKキットおよび関連製品はこちらからダウンロードできます。
      Javaのインストールについては、このOBEの対象外です。 詳しくは、JDKのダウンロードとインストールに関するページを参照してください。
    • Javaアノテーションに関する実用的な知識を有していること。

    このチュートリアルを実行する前に、Oracle Coherence 3.7.1と関連するサンプル・ソース・コードをダウンロードし、インストールしてください。 以下の手順ではCoherence 3.7.1のインストール・プロセスと期待されるインストール先について確認します。すでにCoherence 3.7.1をインストールしている場合は、この手順をスキップしてください。

      上記のリンクにアクセスし、ライセンス契約に同意して、Coherence 3.7.1をダウンロードします。
      このチュートリアルでは、ファイルを/tmp/にダウンロードし、/opt内にインストールすることを想定しています。

      コマンド・プロンプトを開いて、現在のディレクトリをOracle Coherenceのインストール先へ変更します。

      以下のようなコマンドを使用して、Coherence zipの内容を解凍します。

      unzip /tmp/coherence-java-3.7.1...zip 

      正確なファイル名はこれとは異なる場合があります。

      このチュートリアルでは、すべてのファイルが/opt/coherenceに解凍されます。


      以下のようなコマンドを使用して、OBEサンプル・コードの内容を解凍します。
      unzip /tmp/CQL.OBE.src.zip


フィルタとSELECTを使用したCoherenceキャッシュの問合せ

    フィルタ

    Coherenceでは、キャッシュ・データの問合せのためにフィルタ・メカニズムを使用します。 フィルタは、等価、大なり、小なりなどの演算のコレクションが一連の論理演算と組み合わされて、キャッシュ内にある特定のデータセットを返すという点で、問合せ文と似ています。さらに、フィルタをNamedCache.entrySetメソッドと共に使用することで、結果が返されます。

    フィルタのサンプルには以下のものがあります(これらのサンプルはすべて、com.tangosol.util.filter.*パッケージ内にあります)。

    • AndFilter - 他の2つのフィルタの論理積("and")を返します。
    • OrFilter - 他の2つのフィルタの論理和("or")を返します。
    • LikeFilter - 値を比較し、パターン・マッチングを行います。 パターンには通常の文字の他、ワイルドカード文字'_'と'%'が含まれます。
    • EqualsFilter - 値を比較し、ある定数と等しいかどうかを判定します。

    これらの例は利用可能なフィルタのほんの一部です。フィルタの一覧については、Oracle Coherenceのドキュメントを参照してください。

    以下は、Personオブジェクトに年齢、名、姓の各属性が含まれていると想定した場合のフィルタの例です。
    • Filter greaterThen = new GreaterFilter( new ReflectionExtractor("getAge"), 16);
    • Filter lessThen = new LessFilter(new ReflectionExtractor("getAge"), 50));

    これらの2つのフィルタを組み合わせると、以下のようなフィルタになります。
    • Filter and = new AndFilter( greaterThen,lessThen);

    サンプル

    以下のコードがあるとします。
          NamedCache cache = . . .;

    この場合、以下のようにコールして問合せを実行します。
       cache.entrySet(filter,null);


    ここで、第2引数のnullは、結果のソートに使用するためのコンパレータを表すことに注意してください。

    オブジェクト内のフィールド/データ・アクセスに関する注意点: オブジェクト内のデータにアクセスするには、何らかの形式の'エクストラクタ'を使用する必要があります。
    このチュートリアルで使用されるサンプルでは、ReflectionExtractorを使用します。 リフレクション・エクストラクタはメソッド名を引数にとり、そのメソッド名をオブジェクトに適用して値を返します。
    getAge、getFirstNameのようなメソッドを含む適切なキャッシュ・オブジェクトがあるとすると、 ReflectionExtractor("getAge")のような文を使用してリフレクション・エクストラクタを指定し、オブジェクトのageフィールドの値を取得できます。 エクストラクタについて詳しくは、Extractorsパッケージのページを参照してください。

    環境の設定

      POFのテストを簡単に実行するためのさまざまなスクリプトが提供されています。これらのスクリプトは特定の環境変数設定に依存しています。
      これらの変数に対しては適切なデフォルト値があり、このデフォルト値が正しい場合は値を変更する必要はありません。

      これらのスクリプトの前提条件は以下のとおりです。
      • Coherenceが/opt/coherenceにインストールされていること。
      • OBEソースが/opt/CQL.OBEに解凍されていること。

      これらのいずれかの値が異なる場合は、以下の手順に従ってください。

      コマンド・プロンプト・ウィンドウで、OBEソースの解凍先ディレクトリへ移動します。

      cd /opt/{obe source directory}

      任意のエディタで、bin/set-env.shスクリプトを開きます。

      gedit bin/set-env.sh

      スクリプトの上部に、OBEソースとCoherenceの場所を指定した2つのEXPORT文があります。
      これらの2つの変数をコメント解除し、お使いの環境に合った値に設定します。

      /opt/coherenceおよび/opt/CQL.OBEというデフォルト値を使用している場合は、このスクリプトを変更する必要はありません。

      #!/bin/bash

      export OBE_HOME=/opt/my.cql.obe.location
      export COH_HOME=/opt/my.coherence.location

      変更内容を保存し、エディタを終了します。

    Filterをサポートするためのクラスの修正


      このチュートリアルでは、以下の2つのサンプル・エンティティ・オブジェクト・クラスを例として使用します。

      • example.entity.Person.java - 人を表現したクラス。名前、性別、年齢、住所などの特徴を定義している。
      • example.entity.Address.java - 住所を表現したクラス。都道府県、市区町村、番地などが含まれる。

      これらの2つのクラスは、Java Serializableをデフォルトで実装しているため、変更を加えずにCoherenceキャッシュと共に使用できます。 さらに、PersonクラスはJava Comparableインタフェースも実装しており、問合せ内で使用したときには、姓に基づいて結果がソートされます。

      これらに加えて、テスト・データの生成のためや、問合せ機能を開発する出発点として使用できる、以下のようなさまざまなクラスが提供されています。
      • example.test.RunQuery.java - キャッシュにアクセスするための定型的なコードが含まれるクラスであり、このチュートリアルを進める中で修正します。
      • example.simulation.DriverおよびSimulation - キャッシュの相互作用のシミュレートを行うために使用するクラスであり、実行時に'dist-person'キャッシュのデータの追加、変更、削除を行います。

      以下の手順では、問合せの実行のために既存のクラスを修正し、シミュレーションを開始して、最後に問合せを実行します。


      具体的には、名が'Al'で始まり、年齢が17歳以上かつ49歳以下であるすべてのPersonオブジェクトを返すようにフィルタを定義します。
      コマンド・プロンプトを開いて、OBEソースの解凍先ディレクトリへ移動します。

      geditを使用して、src/java/example/RunQuery.javaクラスを開きます。

      gedit src/java/example/RunQuery.java class

      この項で説明するコードの完全版は次の場所にあります。 {OBE_HOME}/completed/1.RunQuery.java
      getFilterメソッドを探します。このメソッドの内容は以下のとおりです。

      public Filter getFilter() {
          /*
           * Enter filter here
           */
          return null;
      }

      フィルタは2つの数値、Filterallフィルタで構成されており、これらをまとめた結果は、上記で説明したような文になります。
      コメントのすぐ下に、以下のような大なりフィルタと小なりフィルタを入力します。

      Filter lower = new GreaterFilter(new ReflectionExtractor("getAge"), 16);
      Filter upper = new LessFilter(new ReflectionExtractor("getAge"), 50);


      部分的に完成したコードは以下のようになります。

      :必要なIMPORT文がすでに追加されています。すべてのフィルタはcom.tangosol.util.filter.*パッケージ内にあります。
      2つ目のFILTER文の下に、年齢の上限と下限を組み合わせるためのAND文を追加します。この新しい文は以下のようになります。

      Filter and = new AndFilter(lower,upper);

      andフィルタの下に、名前でフィルタするための文を追加します。この文は以下のようになります。

      Filter name = new LikeFilter("getFirstName", "Al%");

      AllFilterを使用して、全体の結果を1つの文にまとめることができます。AllFilterを追加して、このメソッドの最終的な結果を返します。 この文は以下のようになります。

      Filter all =  new AllFilter(new Filter[] { and,name });
      return all;

      完成後のメソッドは以下のようになります。

      変更内容を保存し、エディタを終了します。

    フィルタのビルドとテスト

      複数のスクリプトを使用してテストのビルドと実行を行います。これらのスクリプトのおもな目的は、開発用の環境を指定して、正しいクラスパスや関連する考慮事項などのテストの問題を緩和することです。
      • bin/build.sh - すべてのソース・コードを再コンパイルし、再パッケージ化する。
      • bin/start-sim.sh - シミュレーションを開始する。このシミュレーションでは、Personオブジェクトを生成してキャッシュに追加した後、時間をかけてオブジェクトをランダムに変更する。
      • bin/stop-sim.sh - シミュレーションのスクリプトを停止する。
      • bin/check-sim.sh - シミュレーションのプロセスに関連付けられたPIDが実行中であるかをレポートする。
      • bin/runquery.sh - 問合せテスト・アプリケーションを実行する。
      コマンド・ウィンドウで、提供されているビルド・スクリプトを使用してソースを再ビルドします。 コンパイル・エラーが発生した場合は、修正します。

      bin/build.sh

      このコマンドは、以下のような出力を生成します。
      以下のようなコマンドを使用して、シミュレーションを開始します。

      bin/start-sim.sh

      このコマンドは、以下のような出力を生成します。
      シミュレーションを1分以上実行してデータを生成し、以下のようなコマンドを使用して、開始したシミュレーションの出力にエラーがないかを検証します。

      tail -f sim.0.log

      以下のような出力が表示されます。 このシミュレーションではPersonオブジェクトがランダムに生成されるため、表示される内容は一致しません。

      更新後の問合せアプリケーションを実行します。

      bin/runquery.sh > query.log 2>&1


      問合せを正しく記述している場合は、このコマンドは、以下のような出力を生成します。lessgeditなどのツールを使用して、結果を検証します。

    CohQLを使用するための問合せの修正

      Coherence問合せ言語(CQL)はSQLに似た言語であり、SELECTスタイルの文でキャッシュ・データにアクセスするために使用できます。
      CQLの使用方法によって、完全なSELECT文を指定する場合もあれば、WHERE句のみを指定する場合もあります。また、CQLでは実行時の変数および値の入力をサポートしており、問合せをハード・コーディングする必要はありません。

      たとえば、Coherenceコマンドライン・ツールを使用する場合は、SELECT、FROM、WHEREを含む完全な文が必要になります。 一方、アプリケーション内では、特定のNamedCacheインスタンスを使用する場合に、SELECT文のWHERE部分のみが必要になります。 この項では、アプリケーションで利用する場合のみを取り上げます。

      問合せのおもな要素は以下のとおりです。
      • SELECT - select {field set} from "{cache}" where {where clause}.  
      • QueryHelper - com.tangosol.util.QueryHelper。ファクトリ・メソッドのセットを提供するクラスであり、Filterオブジェクトのインスタンスを生成するために使用できます。
        QueryHelperについて詳しくは、こちらを参照してください。

      問合せアプリケーションを開きます。

      gedit src/java/example/RunQuery.java class

      この項で説明するコードの完全版は以下の場所にあります。

      completed/2.RunQuery.java

      前項までに更新したgetFilterメソッドを探し、その内容を削除します。
      名がAlで始まり、年齢が16歳よりも大きく50歳よりも小さいすべてのPersonオブジェクトを検索するためのWHERE句の文を作成します。

      更新後のメソッドは以下のようになります。

      public Filter getFilter() {
          String where = "firstName like 'Al%' and (age > 16 and age < 50)";

      }

      QueryHelperを使用してWHERE句に基づいたフィルタを返す文を追加し、メソッドを完成させます。
      適切なcom.tangosol.util.QueryHelperのIMPORT文がすでに追加されています。

      Filter filter = QueryHelper.createFilter(where); return filter;


      完成後のメソッドは以下のようになります。
      変更内容を保存し、エディタを終了します。
      コマンド・ウィンドウで、提供されているビルド・スクリプトを使用してソースを再ビルドします。

      bin/build.sh

      コンパイル・エラーが発生した場合は、必要に応じて修正します。
      [オプション] シミュレーションが実行中であることを確認します。
      シミュレーションでは、実行時間などのシミュレーションの実行方法を定義するための一連の構成ファイルを使用します。
      デフォルトのシミュレーションの実行時間は60分です。check-sim.shスクリプトを使用して、シミュレーションが実行中かを確認できます。このスクリプトは、シミュレーションの既知のPIDセットを調査し、それらが実行中かどうかを確認します。このスクリプトを実行するには、以下のように入力します。

      bin/check-sim.sh


      このコマンドは、以下のような出力を生成します。



      シミュレーションが完了している場合は、このコマンドは、以下のような出力を生成します。



      この場合は、bin/start-sim.shコマンドを使用して単純にシミュレーションを再起動します。
      問合せアプリケーションを実行します。

      bin/runquery.sh > query.log 2>&1


      問合せを正しく記述している場合は、このコマンドは、前項とほぼ同様の結果を生成します。
      データの生成後は、常に変更されているため、結果が完全には一致しない場合があります。

EXPLAIN PLAN文およびTRACE文の操作

    EXPLAIN PLANとTRACE

    アプリケーションでcom.tangosol.util.aggregator.QueryRecorderクラスを使用して問合せのプロファイルを設定できます。このクラスのドキュメントはこちらにあります。

    このプロセスは、QueryRecorderインスタンスを作成し、次にNamedCache.aggregate(filter,agent)メソッドを使用してそのインスタンスをキャッシュに送信して実行することによって機能します。

    このメソッドは、クラスタのすべてのメンバーに対して指定したフィルタを検証し、QueryResultレコードを返します。このレコードを調査することで、問合せの実行方法を理解できます。

    サンプル

    QueryRecorder.RecordTypeに基づくインスタンスを作成し、そのインスタンスをキャッシュに渡して実行することで、EXPLAINまたはTRACEのためのQuery Recorderをインスタンス化できます。

    一般的には、以下の記述が必要です。

    IMPORT文

    import com.tangosol.util.aggregator.QueryRecorder;
    import static com.tangosol.util.aggregator.QueryRecorder.RecordType;


    ここではstaticを使用して、後でRecordTypeの完全修飾を記述しなくて済むようにしています。

     レコーダの作成と実行:

    QueryRecorder agent = new QueryRecorder(RecordType.EXPLAIN);
    Object resultsExplain = cache.aggregate(filter, agent);

    結果の出力:

    System.out.println("\n" + resultsExplain + "\n");


    EXPLAIN PLANの検証と評価
    Name                                  Index        Cost      ======================================================================================com.tangosol.util.filter.AndFilter  | ----       | 0           LikeFilter(.getFirstName(), Al%)  | 0          | 2300000           com.tangosol.util.filter.AndFilte | ----       | 0             GreaterFilter(.getAge(), 16)    | 1          | 2300000             LessFilter(.getAge(), 50)       | 1          | 2300000         Index LookupsIndex  Description                               Extractor             Ordered   ======================================================================================0      No index found                            .getFirstName()       false1      No index found                            .getAge()             false 


    この出力は以下のように評価できます。

    • Name – この列には、問合せ内の各フィルタの名前が示されます。 複合フィルタの場合、複合フィルタ内部にあるフィルタごとに情報が示されます。

    • Index – この列には、そのフィルタで索引を使用できるかどうかが示されます。 索引が見つかった場合は、Cost表の下にあるIndex Lookups表に、索引数が表示されます。
    • Cost – この列には、フィルタを適用するための見積もりコストが示されます。
      索引を使用できる場合は、コストは1となります。索引を適用する操作で索引の内容に1回アクセスする処理だけが必要になるからです。

      この例では、記憶域を有効にしたクラスタ・メンバーが3つあるため、このコストには、3つのメンバーのそれぞれに存在する索引へのアクセスが反映されています。 索引が存在しない場合は、コストは、EVAL_COST*キー数として計算されます。ここで、EVAL_COSTは定数値1000です。各行には、フィルタを使用してキー・セットを削減するために全体スキャンを実行した場合の相対コストが示されます。

      この例では、評価する必要のある1500個以下のキャッシュ・エントリが存在します。 索引付きのエントリの問合せは、索引付きではないエントリよりも比較的コストが低くなりますが、かならずしも有効性が保証されるわけではありません。


    問合せトレースの検証と評価

    TRACEは、提供されたデータセットに対して問合せを実際に実行して時間を計測し、各索引の相対的な有効性を評価するという点で、EXPLAIN PLANとは異なります。

    TRACEを使用する際には、以下のように単純にRecordType.EXPLAINの代わりにRecordType.TRACEを使用してレコーダを作成します。

    QueryRecorder agent = new QueryRecorder(RecordType.TRACE)

    結果のレポートは前項とは大きく異なります。
    TraceName                                  Index        Effectiveness          Duration  ======================================================================================com.tangosol.util.filter.AndFilter  | ----       | 12852|1386(89%)      | 134         LikeFilter(.getFirstName(), Al%)  | 0          | 12852|2142(83%)      | 85          com.tangosol.util.filter.AndFilte | ----       | 2142|1386(35%)       | 42            GreaterFilter(.getAge(), 16)    | 1          | 2142|2058(3%)        | 17            LessFilter(.getAge(), 50)       | 1          | 2058|1386(32%)       | 24        Index LookupsIndex  Description                               Extractor             Ordered   ======================================================================================0      SimpleMapIndex: Extractor=.getFirstName(  .getFirstName()       true1      SimpleMapIndex: Extractor=.getAge(), Ord  .getAge()             true++++++++
    TRACEの出力は以下のように解釈できます。
        
    • Name – この列には、問合せ内の各フィルタの名前が示されます。 複合フィルタの場合、複合フィルタ内部にあるフィルタごとに情報が示されます。
    • Index – この列には、そのフィルタで索引を使用できるかどうかが示されます。 索引が見つかった場合は、Index Lookups表に、索引数が表示されます。
    • Effectiveness – この列には、各フィルタの結果として実際に削減されたキー・セット数が示されます。 この値はフィルタ前のキー・セット・サイズ | フィルタ後のキー・セット・サイズであり、さらにパーセント値も表示されます。 フィルタ前のキー・セット・サイズの値は、フィルタの評価や索引の適用の前のキー・セット・サイズを表します。 フィルタ後のキー・セット・サイズの値は、フィルタの評価や索引の適用の後に残っているキー・セットのサイズを表します。 複合フィルタ・エントリの場合は、この値は、含まれているフィルタ全体を合計した結果です。 キー・セット・サイズが索引に基づいて削減できなくなった後は、結果のキー・セットはデシリアライズされ、索引付きではないフィルタが適用されます。
    • Duration – この列には、フィルタの評価や索引の適用にかかった時間(ミリ秒単位)が示されます。 値が0の場合、ここに登録されている時間はレポートのしきい値を下回っていることを示します。

    EXPLAIN PLANの使用


      この項では、EXPLAIN PLANを使用して問合せの検証とテストを実行し、問合せおよび関連する索引のコストを判定するようにRunQuery.javaクラスを修正します。
      問合せアプリケーションを開きます。

      gedit src/java/example/RunQuery.java class

      この項で説明するコードの完全版は以下の場所にあります。

      completed/3.RunQuery.java

      executeQueryメソッドを探します。このメソッドの内容は以下のとおりです。

      /**
        * Execute the provided query against the named cache.
        */
      public void executeQuery() {

          dumpReturnedEntries(getNamedCache(), getFilter());

          /*
           * Enter trace and/or explain plan code here.
           */
      }

      コメントのすぐ下に、キャッシュおよび問合せで使用するフィルタのインスタンスを取得するコードを追加します。

      getNamedCache()getFilter()はすでに用意されているか、前項までに作成しています。

      追加するコードは以下のようになります。

      NamedCache cache = getNamedCache();
      Filter filter = getFilter();


      問合せレコーダのインスタンスを取得して実行するためのコードを追加します。

      追加するコードは以下のようになります。

      QueryRecorder agent = new QueryRecorder(RecordType.EXPLAIN);
      Object results = cache.aggregate(filter, agent);


      注:必要なIMPORT文はすでに追加されています。以下のような文です。

      import com.tangosol.util.aggregator.QueryRecorder;
      import static com.tangosol.util.aggregator.QueryRecorder.RecordType;

      最後に、結果を表示するためのコードを追加します。この文は以下のようになります。

      System.out.println("\n" + results + " \n");

      完成後のメソッドは以下のようになります。
      更新後のコードをビルドして実行します。
      simが実行中であることを確認します。

      bin/check-sim.sh

      コードをビルドします。

      bin/build.sh

      コンパイル・エラーを修正し、問合せを実行します。

      bin/runquery.sh > query.log 2>&1

      geditまたはlessを使用して出力を調査し、Explain Planを検索します。

      この結果は以下のようになります。

    索引の追加と結果の検証


      前項では、EXPLAIN PLANを使用して問合せのコストを検証しました。 次に、索引を使用してパフォーマンスを改善できます。 この項では、さまざまな値に索引を追加した後の問合せを検証します。
      問合せアプリケーションを開きます。

      gedit src/java/example/RunQuery.java class

      この項で説明するコードの完全版は以下の場所にあります。

      completed/4.RunQuery.java

      executeQueryメソッドを探し、このメソッド内部のQueryRecorderの前に、AgeフィールドおよびFirstNameフィールドに索引を設定するためのコードを追加します。
      新しいコードは以下のようになります。

      cache.addIndex(new ReflectionExtractor("getAge"), true, null);
      cache.addIndex(new ReflectionExtractor("getFirstName"), true, null);

      [オプション] 索引を削除するためのコードを追加します。

      System.out行の後に、索引を削除するためのコードを追加します。索引削除用のコードは以下のようになります。

      cache.removeindex(new="" reflectionextractor("getfirstname"));
      cache.removeIndex(new ReflectionExtractor("getAge"));

      更新後のメソッドは以下のようになります。


      変更内容を保存し、エディタを終了します。
      更新後のコードをビルドして実行します。
      simが実行中であることを確認します。

      bin/check-sim.sh

      コードをビルドします。

      bin/build.sh

      コンパイル・エラーを修正し、問合せを実行します。

      bin/runquery.sh > query.log 2>&1

      結果を検証します。

      geditまたはlessを使用して出力を調査し、Explain Planを検索します。問合せのコストが大幅に減少している点に注意してください。

      この結果は以下のようになります。

    TRACEとEXPLAIN PLANの比較


      この項では、索引の相対的な有効性を判断できるように、RunQuery.javaクラスを修正します。
      問合せアプリケーションを開きます。

      gedit src/java/example/RunQuery.java class

      この項で説明するコードの完全版は以下の場所にあります。

      completed/5.RunQuery.java

      executeQueryメソッドを探し、問合せレコーダをRecordType.TRACEタイプに変更します。
      完了後のメソッドは以下のようになります。

      QueryRecorder agent = new QueryRecorder(RecordType.TRACE);

      変更内容を保存し、エディタを終了します。
      更新後のコードをビルドして実行します。
      simが実行中であることを確認します。simが数分間実行されていることも確認してください。

      bin/check-sim.sh

      コードをビルドします。

      bin/build.sh

      コンパイル・エラーを修正し、問合せを実行します。

      bin/runquery.sh > query.log 2>&1

      TRACEの出力を検証します。以下は出力例です。

      質問: age索引を使用した場合の有効性はどの程度ですか。
      [オプション] age索引を削除します。 問合せを再ビルドして再実行します。 結果はどうなりましたか。

Coherence問合せコマンドライン・ツールの使用

    Coherenceでは、コマンドラインからデータの問合せを行うメカニズムが提供されています。 com.tangosol.coherence.dslquery.QueryPlusクラスは、データベースの問合せに通常使用する機能の大部分を実装しています。
    QueryPlusのサポート対象は以下のとおりです。
    • SELECT - キャッシュから選択する。
    • INSERT - 要素をキャッシュに挿入する。
    • DELETE - キャッシュから要素を削除する。
    • CREATE INDEX - キャッシュに対して索引を作成する。
    • DROP INDEX - キャッシュから索引を削除する。
    • その他
    • サポート対象のコマンドと各コマンドの構文の一覧については、こちらを参照してください。
    コマンド・プロンプトで、提供されているbin/querytool.shを使用してQuery Plusアプリケーションを起動します。

    bin/querytool.sh

    注:必要な場合は、bin/check-sim.shスクリプトを使用してシミュレーションが実行中であることを確認します。
    以下のようなCohQL>プロンプトが表示されます。
     

    注:
    コマンドライン編集が有効になるため、矢印キーを使用して以前に入力したコマンドの取得や編集を行うことができます。
    CohQL>プロンプトで、以下のように入力します。

    select * from "dist-person" [CR]

    [CR]は改行を表します。実際の文字を入力するわけではありません。

    Personオブジェクトのセットが返されます。
    キャッシュから名、姓、年齢のみを選択します。

    select FirstName, LastName, Age from "dist-person" 

    名がAlで始まり、年齢が15歳より大きく50歳より小さいことを示すWHERE句を追加します。

    select FirstName,LastName,Age from "dist-person" where age > 15 and age < 50 and FirstName like "Al%"

    traceコマンドを使用して実行のトレースを行います。

    trace select FirstName,LastName,Age from "dist-person" where age > 15 and age < 50 and FirstName like "Al%"

    explain plan forコマンドを使用して、コマンドの実行を検証します。

    explain plan for select FirstName,LastName,Age from "dist-person" where age > 15 and age < 50 and FirstName like "Al%"

    create indexを使用して、名に対して索引を追加します。

    create index "dist-person" FirstName;

    traceコマンドとexplain plan forコマンドを再実行して、索引の追加による影響を評価します。

    trace select FirstName,LastName,Age from "dist-person" where age > 15 and age < 50 and FirstName like "Al%"

    explain plan for select FirstName,LastName,Age from "dist-person" where age > 15 and age < 50 and FirstName like "Al%

    drop indexを使用して、名の索引を削除します。

    drop index "dist-person" FirstName

    Query Plusを終了します。

    quit

まとめ

    このチュートリアルで学習した内容は、以下のとおりです。

    • 基本的なFilterクラスとQueryHelperクラスを使用してキャッシュの問合せを行う
    • Explain Planを使用して問合せのパフォーマンスを見積もる
    • 問合せのパフォーマンスとフィルタの影響度を評価する
    • Coherence問合せアプリケーションを使用して問合せ方法を確認する

    参考資料

    • Oracle Coherence 3.7.1のドキュメントは、こちらを参照してください。
    • Oracle Coherenceの開発と管理に関するさまざまなクラスおよび上級者向けトレーニングは、こちらで検索できます。
    • Oracle Coherenceについて、詳しくはOracle Learning Libraryにあるその他のOBEを参照してください。

    著者

    • カリキュラム開発責任者: Al Saganich
    • 共著者: Jason Howes、Tim Middleton、Noah Arliss他

このOracle by Exampleをナビゲートする際、次の機能を使用できます。

ヘッダー・ボタンの非表示:
ヘッダー内のボタンを非表示にするには、タイトルをクリックします。 ボタンを再表示するには、もう一度タイトルをクリックします。
トピック一覧ボタン:
すべてのトピックの一覧です。 いずれかのトピックをクリックすると、その項に移動します。
すべてのトピックを開く/閉じる:
すべての項に対する詳細を表示または非表示にします。 デフォルトでは、すべてのトピックが閉じられています。
すべてのイメージを表示/非表示:
すべてのスクリーンショットを表示または非表示にします。 デフォルトでは、すべてのイメージが表示されています。
印刷:
コンテンツを印刷します。 現在表示または非表示にされているコンテンツが印刷されます。

このチュートリアルの特定の項に移動するには、一覧からトピックを選択してください。