

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# `joinOrder` SPARQL クエリヒント
<a name="sparql-query-hints-joinOrder"></a>

SPARQL クエリを送信すると、Amazon Neptune クエリエンジンはクエリの構造を調査します。クエリの各パートの順序を変更し、評価に必要な作業の量とクエリレスポンス時間を最小限にしようとします。

たとえば、一連の接続された 3 つのパターンは通常、指定された順序では評価されません。ヒューリスティックと統計 (個々のパターンの選択性と共有変数で接続される方法など) を使用して順序が変更されます。さらに、サブクエリ、FILTER、複雑な OPTIONAL や MINUS ブロックなど、より複雑なパターンがクエリに含まれている場合、Neptune クエリエンジンは評価の順序を効率的にするために、可能な限りそれらの順序を変更します。

より複雑なクエリでは、Neptune で選択されるクエリの評価順序は常に最適であるとは限りません。たとえば、Neptune では、クエリ評価中に発生するインスタンスデータ固有の特性 (グラフでの power ノードの発生など) を見逃す可能性があります。

データの正確な特性がわかっていて、クエリ実行の順序を手動で指定する場合は、Neptune `joinOrder` クエリヒントを使用して特定の順序でクエリが評価されるように指定します。

## `joinOrder` SPARQL ヒント構文
<a name="sparql-query-hints-joinOrder-syntax"></a>

`joinOrder` クエリヒントは、SPARQL クエリに含まれる 3 つのパターンとして指定されます。

わかりやすくするために、次の構文では、クエリに定義されて含まれる `hint` プレフィックスを使用して Neptune クエリヒント名前空間を指定します。

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
scope hint:joinOrder "Ordered" .
```

**利用可能なスコープ**
+ `hint:Query`
+ `hint:Group`

クエリヒントスコープの詳細については、「[Neptune における SPARQL クエリヒントの範囲。](sparql-query-hints.md#sparql-query-hints-scope)」を参照してください。

## `joinOrder`SPARQL ヒントの例
<a name="sparql-query-hints-joinOrder-example"></a>

このセクションでは、`joinOrder` クエリヒントを使用した場合と使用していない場合に記述されたクエリ、および関連する最適化を示します。

この例では、データセットに次のものが含まれていることを前提としています。
+ `Jane` を含む 1,000 人に `:likes` エッジを持つ (「いいね！」した) `John` という名前の 1 人の人物。
+ `John` を含む 10 人に `:likes` エッジを持つ (「いいね！」した) `Jane` という名前の 1 人の人物。

**クエリヒントなし**  
次の SPARQL クエリは、一連のソーシャルネットワーキングデータから相互に「いいね！」した `John` と `Jane` という名前のすべての人物のペアを抽出します。

```
PREFIX : <https://example.com/>
SELECT ?john ?jane {
  ?person1 :name "Jane" .
  ?person1 :likes ?person2 .
  ?person2 :name "John" .
  ?person2 :likes ?person1 .
}
```

Neptune クエリエンジンは、記述とは異なる順序でステートメントを評価する可能性があります。たとえば、次の順序で評価するように選択される場合があります。

1. `John` という名前の人物をすべて検索します。

1. `:likes` エッジによって `John` に接続されているすべての人物を検索します。

1. `Jane` という名前の人物でこのセットをフィルタリングします。

1. `:likes` エッジによって `John` に接続されている人物でこのセットをフィルタリングします。

データセットによると、この順序で評価すると 2 番目のステップで 1,000 のエンティティが抽出されます。これは 3 番目のステップで 1 つのノード `Jane` に絞り込まれます。そして最後のステップで、`Jane` も `John` ノードに対して `:likes` エッジを持っていると判断されます。

**クエリヒント**  
`Jane` ノードには発信 `:likes` エッジが 10 個しかないため、このノードから開始する方が有利です。これにより、2 番目のステップで 1,000 のエンティティを抽出することを回避し、クエリの評価中の作業量を低減できます。

次の例では **joinOrder** クエリヒントを使用し、クエリの自動結合の順序変更をすべて無効にすることで、`Jane` ノードとその発信エッジが最初に処理されるようにします。

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ?john ?jane {
  hint:Query hint:joinOrder "Ordered" .
  ?person1 :name "Jane" .
  ?person1 :likes ?person2 .
  ?person2 :name "John" .
  ?person2 :likes ?person1 .
}
```

応用できる現実社会のシナリオとしては、ネットワーク内の人物を「コネクションが多いインフルエンサー」や「コネクションが少ない通常のユーザー」に分類する、ソーシャルネットワークへの応用などが挙げられます。このようなシナリオでは、前述の例のようなクエリで、インフルエンサー (`John`) の前に通常のユーザー (`Jane`) が処理されるようになっていることを確認します。

**クエリヒントと順序変更**  
この例をさらに一歩進めることができます。`:name` 属性が単一のノードに固有であることがわかっている場合は、`joinOrder` クエリヒントの順序を変更して使用することで、クエリの時間を短縮することができます。このステップでは、最初に一意のノードが抽出されるようにします。

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ?john ?jane {
  hint:Query hint:joinOrder "Ordered" .
  ?person1 :name "Jane" .
  ?person2 :name "John" .
  ?person1 :likes ?person2 .
  ?person2 :likes ?person1 .
}
```

この場合、各ステップで以下の単一のアクションへのクエリを減らすことができます。

1. `:name` `Jane` を持つ 1 人の人物のノードを検索します。

1. `:name` `John` を持つ 1 人の人物のノードを検索します。

1. 最初のノードが 2 番目のノードに `:likes` エッジで接続されていることを確認します。

1. 2 番目のノードが最初のノードに `:likes` エッジで接続されていることを確認します。



**重要**  
間違った順序を選択した場合、`joinOrder` クエリヒントのパフォーマンスが大幅に低下する可能性があります。たとえば、前述の例は `:name` 属性が一意でない場合、非効率的です。100 ノードすべての名前が `Jane` で 1,000 ノードすべての名前が `John` の場合、クエリで 1,000 \$1 100 (100,000) ペアの `:likes` エッジを確認することになります。