第2章 Ickle クエリーの作成
Data Grid は、リレーショナルクエリーとフルテキストクエリーを作成可能にする Ickle クエリー言語を提供します。
2.1. Ickle クエリー
API を使用するには、まず QueryFactory をキャッシュに取得してから、.create()
メソッドを呼び出し、クエリーで使用する文字列を渡します。各 QueryFactory
インスタンスは Search
と同じ Cache
インスタンスにバインドされますが、それ以外の場合は、複数のクエリーを並行して作成するために使用できるステートレスおよびスレッドセーフオブジェクトになります。
以下に例を示します。
// Remote Query, using protobuf QueryFactory qf = org.infinispan.client.hotrod.Search.getQueryFactory(remoteCache); Query<Transaction> q = qf.create("from sample_bank_account.Transaction where amount > 20"); // Embedded Query using Java Objects QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache); Query<Transaction> q = qf.create("from org.infinispan.sample.Book where price > 20"); // Execute the query QueryResult<Book> queryResult = q.execute();
クエリーは常に単一のエンティティータイプをターゲットにし、単一のキャッシュの内容に対して評価されます。複数のキャッシュでクエリーを実行したり、複数のエンティティータイプ (結合) を対象とするクエリーを作成したりすることは、サポートされていません。
クエリーの実行と結果のフェッチは、Query
オブジェクトの execute()
メソッドを呼び出すのと同じくらい簡単です。実行後に、同じインスタンスで execute()
を呼び出すと、クエリーを再実行します。
2.1.1. ページネーション
Query.maxResults(int maxResults)
を使用して、返される結果の数を制限することができます。これを Query.startOffset(long startOffset)
と組み合わせて使用すると、結果セットのページネーションを実現できます。
// sorted by year and match all books that have "clustering" in their title // and return the third page of 10 results Query<Book> query = queryFactory.create("FROM org.infinispan.sample.Book WHERE title like '%clustering%' ORDER BY year").startOffset(20).maxResults(10)
クエリーインスタンスの maxResults
を明示的に設定しない場合、Data Grid はクエリーによって返される結果の数を 100
に制限します。query.default-max-results
キャッシュプロパティーを設定することで、デフォルトの制限を変更できます。
2.1.2. ヒット数
QueryResult
オブジェクトには .hitCount()
メソッドが含まれています。このメソッドは、ページネーションパラメーターに関係なく、クエリーからの結果の合計数を表すヒット数の値を返します。ヒット数は、パフォーマンス上の理由から、インデックス付きクエリーでのみ使用できます。
2.1.2.1. ヒット数の精度
パフォーマンスを最適化するために、ヒット数のデフォルトの精度は 10000
に設定されています。query.hit-count-accuracy
キャッシュプロパティーを設定することで、必要なヒット数の精度を制限できます。あるいは、各クエリーインスタンスに制限を設定することもできます。
ヒット数が指定された制限を超えると、Data Grid はヒット数の値を返しません。HotRod クライアントまたは埋め込みクエリー API を使用している場合、Data Grid は null
を返し、REST クエリー API を使用している場合、Data Grid は -1L
で応答します。ヒット数の精度を Integer.MAX
に設定すると、どのクエリーに対しても正確な結果が返されますが、クエリーのパフォーマンスに悪影響を及ぼします。
最適なパフォーマンスを得るには、予想されるヒット数よりわずかに大きいプロパティー値を設定します。正確なヒット数が必要ない場合は、低い値に設定します。
2.1.3. 反復
Query
オブジェクトには、結果を遅延して取得するための .iterator()
メソッドがあります。使用後に閉じる必要がある CloseableIterator
のインスタンスを返します。
リモートクエリーの反復サポートは現在制限されています。反復する前に、最初にすべてのエントリーをクライアントにフェッチするためです。
2.1.4. 名前付きクエリーパラメーター
実行ごとに新しい Query オブジェクトを作成する代わりに、実行前に実際の値に置き換えることができる名前付きパラメーターをクエリーに含めることができます。これにより、クエリーを 1 度定義し、複数回効率的に実行できます。パラメーターは、Operator の右側でのみ使用でき、通常の定数値ではなく、org.infinispan.query.dsl.Expression.param(String paramName)
メソッドによって生成されたオブジェクトを Operator に提供することで、クエリーの作成時に定義されます。パラメーターが定義されたら、以下の例に示すように Query.setParameter(parameterName, value)
または Query.setParameters(parameterMap)
のいずれかを呼び出すことで設定できます。
QueryFactory queryFactory = Search.getQueryFactory(cache); // Defining a query to search for various authors and publication years Query<Book> query = queryFactory.create("SELECT title FROM org.infinispan.sample.Book WHERE author = :authorName AND publicationYear = :publicationYear").build(); // Set actual parameter values query.setParameter("authorName", "Doe"); query.setParameter("publicationYear", 2010); // Execute the query List<Book> found = query.execute().list();
または、実際のパラメーター値のマップを指定して、複数のパラメーターを一度に設定することもできます。
複数の名前付きパラメーターを一度に設定する
Map<String, Object> parameterMap = new HashMap<>(); parameterMap.put("authorName", "Doe"); parameterMap.put("publicationYear", 2010); query.setParameters(parameterMap);
クエリーの解析、検証、および実行計画の作業の大部分は、パラメーターでのクエリーの最初の実行時に実行されます。この作業は後続の実行時には繰り返し行われないため、クエリーパラメーターではなく定数値を使用した同様のクエリーの場合よりもパフォーマンスが向上します。
2.1.5. クエリーの実行
Query
API は、キャッシュで Ickle クエリーを実行する 2 つの方法を提供します。
-
Query.execute()
は SELECT ステートメントを実行し、結果を返します。 -
Query.executeStatement()
は DELETE ステートメントを実行し、データを変更します。
常に executeStatement()
を呼び出してデータを変更し、execute()
を呼び出してクエリーの結果を取得する必要があります。