

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# `joinOrder` SPARQL 查詢提示
joinOrder

當您提交 SPARQL 查詢時，Amazon Neptune 查詢引擎會調查查詢的結構。它會重新排序部分查詢，並嘗試將評估所需的工作量和查詢回應時間減到最低。

例如，一系列的連接三重模式通常不會依給定的順序評估。它使用啟發和統計資料 (例如個別模式的選擇性以及它們如何透過共用變數連接) 進行重新排序。此外，如果您的查詢包含更複雜的模式，例如子查詢、FILTER、或複雜的 OPTIONAL 或 MINUS 區塊，Neptune 查詢引擎會盡可能將它們重新排序，致力使評估順序更有效率。

用於更複雜的查詢時，Neptune 選擇評估查詢的順序不一定是最佳的順序。例如，Neptune 可能會錯過在查詢評估期間發生的執行個體資料特定特性 (如圖表中出現 Power 節點)。

如果您知道資料的確切特性，並希望手動指示查詢執行的順序，請使用 Neptune `joinOrder` 查詢提示來指定依給定順序評估查詢。

## `joinOrder` SPARQL 提示語法
語法

`joinOrder` 查詢提示是以三重模式指定，該模式包含在 SPARQL 查詢中。

為更清楚起見，以下語法使用已定義並包含在查詢中的 `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 提示範例
範例

本節示範使用和不使用 `joinOrder` 查詢提示編寫的查詢以及相關的最佳化。

此範例假設資料集包含下列項目：
+ 一個人名為 `John`，且 `:likes` 1,000 個人，包括 `Jane`。
+ 一個人名為 `Jane`，且 `:likes` 10 個人，包括 `John`。

**無查詢提示**  
以下 SPARQL 查詢會從一組社交網路資料中擷取所有名為 `John` 和 `Jane` 且彼此喜歡 (like) 的雙人組：

```
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`」篩選這些人。

根據資料集，以此順序評估的結果是在第二個步驟會擷取 1,000 個實體。第三個步驟則將這些再縮減到單一節點 `Jane`。然後，最終步驟判斷 `Jane` 也 `:likes` `John` 節點。

**查詢提示**  
從 `Jane` 節點開始是有利的，因為她只有 10 個傳出 `:likes` 邊緣。這可藉由避免在第二步驟擷取 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 .
}
```

適用的真實世界案例可以是在社交網路的應用，網路中的人被分類為具有許多連接的影響者或具有少量連接的普通使用者。在這類案例中，以先前範例中的查詢為例，可以確保先處理普通使用者 (`Jane`) 再處理影響者 (`John`)。

**查詢提示和重新排序**  
這個範例可以再進一步處理。如果您知道單一節點的 `: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. 尋找符合 `:name` `John` 的單一個人節點。

1. 確認第一個節點透過 `:likes` 邊緣連接到第二個節點。

1. 確認第二個節點透過 `:likes` 邊緣連接到第一個節點。



**重要**  
如果您選擇錯誤的順序，`joinOrder` 查詢提示可能導致效能大幅下降。例如，如果 `:name` 屬性不是唯一，前述範例的效率會很差。如果 100 個節點的名稱都是 `Jane`，且 1,000 個節點的名稱都是 `John`，則此查詢會造成對 `:likes` 邊緣檢查 1,000\$1 100 (共 100,000 個) 雙人組。