クエリプランの取得

IBM Cloudant Queryがクエリ実行時に使用するインデックスを理解することは、優れたパフォーマンスを達成するために不可欠です。 クエリプランを取得するには _explain エンドポイントを使用します。

インデックスの選択方法

IBM Cloudant 照会では、照会時に索引を指定しない限り、照会に応答するために使用する索引が選択されます。

使用するインデックスを指定しない場合、 IBM Cloudant Query は、以下のロジックを使用します。

  • 照会プランナーはセレクター・セクションを参照し、照会で使用される演算子とフィールドに最も一致する索引を見つけます。 複数の JSON タイプ索引が一致する場合は、索引内のフィールド数が最も少ない索引が優先されます。 2 つ以上の候補索引がまだ存在する場合は、アルファベット順で最初の名前を持つ索引が選択されます。
  • json タイプの索引および text タイプの索引の両方がセレクターを満たす場合、デフォルトで json 索引が選択されます。
  • 以下の条件を満たす場合は、text タイプの索引が選択されます。
    • json タイプの索引と * タイプの索引の*両方がtext 同じフィールド (例えば fieldone など) に存在する。
    • text タイプの索引を使用しないとセレクターを満たすことができない。

例えば、text フィールドに json タイプの索引と foo タイプの索引があり、以下のサンプルのようなセレクターを使用するとします。

{
	"foo": {
		"$in": ["red","blue","green"]
	}
}

text タイプの索引はセレクターを満たすことができないため、IBM Cloudant 照会は json タイプの索引を使用します。

ただし、同じ索引を持つ別のセレクターを使用する場合もあります。

{
	"foo": {
		"$gt": 2
	}
}

この例では、次のようになっています。 IBM Cloudant 照会では、両方のタイプの索引がセレクターを満たすことができるため、 jsonタイプの索引が使用されます。

使用するインデックスの指定

use_indexallow_fallback クエリ・パラメータを使用して、クエリのインデックス使用を制御する。 詳細は クエリパラメータを 参照。

これらのパラメータを使用すると、 _explain 、クエリが指定されたインデックスを使用できるかどうか、つまりクエリが意図したとおりに実行されるかどうかを示すことができる。

_explain エンドポイントを使う

特定の照会で使用されている索引を識別するには、照会をデータとして、データベースの POST エンドポイントに _explain を送信します。 使用中の索引の詳細は、結果内の index オブジェクトに表示されます。

以下の例では、HTTP を使用して照会への応答に使用された索引を識別する方法を示しています。

POST /movies/_explain HTTP/1.1
Host: $SERVICE_URL
Content-Type: application/json
{
	"selector": {
		"$text": "Pacino",
		"year": 2010
	}
}

以下の例では、コマンド・ラインを使用して照会への応答に使用された索引を識別する方法を示しています。

curl "$SERVICE_URL/movies/_explain" \
	-X POST \
	-H "Content-Type: application/json" \
	-d '{
		"selector": {
			"$text": "Pacino",
			"year": 2010
		}
	}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.ExplainResult;
import com.ibm.cloud.cloudant.v1.model.PostExplainOptions;

import java.util.HashMap;
import java.util.Map;

Cloudant service = Cloudant.newInstance();

Map<String, Object> selector = new HashMap<>();
selector.put("$text", "Pacino");
selector.put("year", 2010);

PostExplainOptions explainOptions =
    new PostExplainOptions.Builder()
        .db("movies")
        .selector(selector)
        .build();

ExplainResult response =
    service.postExplain(explainOptions).execute()
        .getResult();

System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';

const service = CloudantV1.newInstance({});

let selector: CloudantV1.Selector = {
    '$text': 'Pacino',
    'year': 2010
};

service.postExplain({
  db: 'movies',
  selector: selector
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

response = service.post_find(
  db='movies',
  selector={'$text': 'Pacino', 'year': 2010}
).get_result()

print(response)
postExplainOptions := service.NewPostExplainOptions(
    "movies",
    map[string]interface{}{
        "$text": "Pacino",
        "year":  2010,
    },
)

explainResult, _, err := service.PostExplain(postExplainOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(explainResult, "", "  ")
fmt.Println(string(b))

前の Go の例では、以下のインポート・ブロックが必要です。

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

この例 _explain レスポンスは、クエリへの回答にどのインデックスが使用されたかを示しています:

{
	"dbname": "$ACCOUNT/movies",
	"index": {
		"ddoc": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8",
		"name": "32372935e14bed00cc6db4fc9efca0f1537d34a8",
		"type": "text",
		"def": {
			"default_analyzer": "keyword",
			"default_field": {},
			"selector": {},
			"fields": []
		}
	},
	"selector": {
		"$and": [
			{
				"$default": {
					"$text": "Pacino"
				}
			},
			{
				"year": {
					"$eq": 2010
				}
			}
		]
	},
	"opts": {
		"use_index": [],
		"bookmark": [],
		"limit": 10000000000,
		"skip": 0,
		"sort": {},
		"fields": "all_fields",
		"r": [
			49
		],
		"conflicts": false
	},
	"limit": 200,
	"skip": 0,
	"fields": "all_fields",
	"query": "(($default:Pacino) AND (year_3anumber:2010))",
	"sort": "relevance"
}