例1: 索引スキャンのみが含まれる問合せ計画でのカバー索引の使用
索引は、その索引のエントリのみを使用して問合せを評価できる場合、つまり、関連付けられた行を取得する必要がない場合、問合せに関するカバー索引と呼ばれます。
州(state)がCAで市(city)の値がS以上で、収入(income)が1000から2000までであるユーザーのID (id)と収入(income)をフェッチします。
SELECT id, income FROM Users u WHERE u.address.state = "CA" AND
u.address.city >= "S" AND 1000 < income and income < 2000
問合せ実行計画:
{
"iterator kind" : "RECEIVE",
"distribution kind" : "ALL_SHARDS",
"input iterator" :
{
"iterator kind" : "SELECT",
"FROM" :
{
"iterator kind" : "TABLE",
"target table" : "users",
"row variable" : "$$u",
"index used" : "idx_state_city_income",
"covering index" : true,
"index row variable" : "$$u_idx",
"index scans" : [
{
"equality conditions" : {"address.state":"CA","address.city":"Santaclara"},
"range conditions" : { "income" : { "start value" : 1000, "start inclusive" : false, "end value" : 2000, "end inclusive" : false } }
}
]
},
"FROM variable" : "$$u_idx",
"SELECT expressions" : [
{
"field name" : "id",
"field expression" :
{
"iterator kind" : "FIELD_STEP",
"field name" : "#id",
"input iterator" :
{
"iterator kind" : "VAR_REF",
"variable" : "$$u_idx"
}
}
},
{
"field name" : "income",
"field expression" :
{
"iterator kind" : "FIELD_STEP",
"field name" : "income",
"input iterator" :
{
"iterator kind" : "VAR_REF",
"variable" : "$$u_idx"
}
}
}
]
}
}
問合せ実行計画の説明:
- この問合せ計画のルート・イテレータは、SELECTイテレータである単一の子(入力イテレータ)がある、RECEIVEイテレータです。この例でのRECEIVEイテレータの唯一のプロパティは、値がALL_SHARDSであるdistribution kindです。
- ここでは索引
idx_state_city_income
が使用されています。また、SELECT式内のすべてのフィールドは索引エントリの使用によってのみフェッチ可能であるため、これはカバー索引です。 - 索引スキャン・プロパティには、実行する索引スキャンを定義する、開始条件と停止条件が含まれています。
この問合せでは、1つの索引スキャンのみが実行されます。等価条件(equality conditions)は、その問合せからのu.address.state = "CA"およびu.address.city = "Santaclara"という条件に対応しています。範囲条件(range conditions)は、1000 < income and income < 2000という条件に対応しています。この索引スキャンは、"index scans" : [ { "equality conditions" : {"address.state":"CA","address.city":"Santaclara"}, "range conditions" : { "income" : { "start value" : 1000, "start inclusive" : false, "end value" : 2000, "end inclusive" : false } } } ]
address.state
フィールドがCAでaddress.city
フィールドがSantaclaraでincome
フィールドが1000より大きい最初のエントリから開始されます。この索引スキャンでは、address.state
フィールドがCAでないか、address.city
フィールドがSantaclaraでないか、income
フィールドが2000以上であるエントリが見つかるまでの、後続のすべてのエントリが返されます。 - index row variableは
$$u_idx
であり、これは、TABLEイテレータによって生成されるすべての索引エントリを対象とする、変数の名前です。索引スキャンによって新しい索引エントリが生成されるたびに、$$u_idx
変数がそのエントリにバインドされます。 - FROMイテレータがTABLEイテレータである場合、FROM variableは、TABLEイテレータのindex row variableまたはrow variableのどちらか(使用されている索引がカバーかどうかで異なる)と同じになります。この例では、SELECT式内のすべてのフィールドは索引エントリの使用によってのみ評価可能であるため索引はカバーであり、FROM variableはindex row variable (
$$u_idx
)と同じになります。 - このindex row variable (
$$u_idx
)は、SELECT式の他の句を実装するイテレータによって参照されます。 - このSELECT式では、2つのフィールド(
id
およびincome
)がフェッチされます。これらは、SELECT式の句にある2つのフィールド名およびフィールド式に対応しています。
このSELECT式によってフェッチされるフィールドごとに、フィールド式がFIELD_STEPイテレータによって計算されます。FIELD_STEPイテレータでは、その入力イテレータで生成されたレコードからフィールド(前述の{ "field name" : "id", "field expression" : { "iterator kind" : "FIELD_STEP", "field name" : "#id", "input iterator" : { "iterator kind" : "VAR_REF", "variable" : "$$u_idx" } } }
id
)の値が抽出され返されます。このSELECT式でフェッチされるフィールドごとに同じことが実行されます。