

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

# 使用 SPARQL 存取 Neptune 圖形
<a name="access-graph-sparql"></a>

SPARQL 是一種資源描述架構 (RDF) 的查詢語言，其是專為網路設計的圖形資料格式。Amazon Neptune 與 SPARQL 1.1 相容。這表示您可以連線到 Neptune 資料庫執行個體，並使用 [SPARQL 1.1 查詢語言](https://www.w3.org/TR/sparql11-query/)規格所述的查詢語言來查詢圖形。

 SPARQL 的查詢包含 `SELECT` 子句，用於指定要傳回的變數，和 `WHERE` 子句，用於指定要比對圖形中的哪些資料。如果您不熟悉 SPARQL 查詢，請參閱 [SPARQL 1.1 查詢語言](https://www.w3.org/TR/sparql11-query/#WritingSimpleQueries)中的[編寫簡易查詢](https://www.w3.org/TR/sparql11-query/)。

**重要**  
若要載入資料，`SPARQL UPDATE INSERT` 可能非常適用於小型資料集，但如果您需要從檔案載入大量資料，請參閱[使用 Amazon Neptune 大量載入器擷取資料](bulk-load.md)。

如需有關 Neptune 之 SPARQL 實作細節的詳細資訊，請參閱 [SPARQL 標準合規](feature-sparql-compliance.md)。

開始之前，您必須準備好以下事項：
+ Neptune 資料庫執行個體。如需建立 Neptune 資料庫執行個體的相關資訊，請參閱 [建立 Amazon Neptune 叢集](get-started-create-cluster.md)。
+ 與您的 Neptune 資料庫執行個體位於同一虛擬私有雲端 (VPC) 的 Amazon EC2 執行個體。

**Topics**
+ [

# 使用 RDF4J 主控台連線到 Neptune 資料庫執行個體
](access-graph-sparql-rdf4j-console.md)
+ [

# 使用 RDF4J Workbench 連線到 Neptune 資料庫執行個體
](access-graph-sparql-rdf4j-workbench.md)
+ [

# 使用 Java 連線至 Neptune 資料庫執行個體
](access-graph-sparql-java.md)
+ [

# SPARQL HTTP API
](sparql-api-reference.md)
+ [

# SPARQL 查詢提示
](sparql-query-hints.md)
+ [

# 關於預設圖形的 SPARQL DESCRIBE 行為
](sparql-default-describe.md)
+ [

# SPARQL 查詢狀態 API
](sparql-api-status.md)
+ [

# SPARQL 查詢取消
](sparql-api-status-cancel.md)
+ [

# 在 Amazon Neptune 中使用 SPARQL 1.1 圖形存放區 HTTP 通訊協定 (GSP)
](sparql-graph-store-protocol.md)
+ [

# 使用 SPARQL `explain` 分析 Neptune 查詢執行
](sparql-explain.md)
+ [

# Neptune 中使用 `SERVICE` 延伸模組的 SPARQL 聯合查詢
](sparql-service.md)

# 使用 RDF4J 主控台連線到 Neptune 資料庫執行個體
<a name="access-graph-sparql-rdf4j-console"></a>



RDF4J 主控台可讓您在 REPL (read-eval-print loop) 環境下試驗資源描述架構 (RDF) 圖表和查詢。

您可從 RDF4J 主控台新增遠端圖形資料庫做為儲存庫和查詢。本小節將逐步引導您完成 RDF4J 主控台的設定，以遠端連線到 Neptune 資料庫執行個體。

**使用 RDF4J 主控台連線到 Neptune**

1. 從 RDF4J 網站的[下載頁面](http://rdf4j.org/download/)下載 RDF4J SDK。

1. 解壓縮 RDF4J SDK zip 檔案。

1. 在終端機上，導覽至 RDF4J SDK 目錄，然後輸入下列命令來執行 RDF4J 主控台：

   ```
   bin/console.sh
   ```

   您應該會看到類似下列的輸出：

   ```
   14:11:51.126 [main] DEBUG o.e.r.c.platform.PlatformFactory - os.name = linux
   14:11:51.130 [main] DEBUG o.e.r.c.platform.PlatformFactory - Detected Posix platform
   Connected to default data directory
   RDF4J Console 3.6.1
   
   3.6.1
   Type 'help' for help.
   >
   ```

   您現在進入 `>` 提示。這是 RDF4J 主控台的一般提示。您可使用此提示設定儲存庫和其他操作。儲存庫有專用可執行查詢的提示。

1. 在 `>` 提示下，輸入以下命令為您的 Neptune 資料庫執行個體建立 SPARQL 儲存庫：

    

   ```
   create sparql
   ```

1. RDF4J 主控台會提示您輸入連接到 SPARQL 端點所需變數的值。

   ```
   Please specify values for the following variables:
   ```

   指定下列值：    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/neptune/latest/userguide/access-graph-sparql-rdf4j-console.html)

   如需尋找 Neptune 資料庫執行個體地址的相關資訊，請參閱 [連線至 Amazon Neptune 端點](feature-overview-endpoints.md) 一節。

   如果操作成功，您會看到以下訊息：

    

   ```
   Repository created
   ```

1. 在 `>` 提示下，輸入以下命令以連線到 Neptune 資料庫執行個體：

   ```
   open neptune
   ```

   如果操作成功，您會看到以下訊息：

    

   ```
   Opened repository 'neptune'
   ```

   您現在進入 `neptune>` 提示。在此提示下，您可以針對 Neptune 圖形執行查詢。

    
**注意**  
既然您已新增儲存庫，您下次執行 `bin/console.sh` 時便能立即執行 `open neptune` 命令以連線到 Neptune 資料庫執行個體。

1. 在 `neptune>` 提示下，輸入下列命令執行 SPARQL 查詢，使用 `?s ?p ?o` 查詢和限制 10，以傳回圖形中的最多 10 個三元組 (subject-predicate-object)。若要查詢其他內容，請將 `sparql` 命令之後的文字換成其他的 SPARQL 查詢。

   ```
   sparql select ?s ?p ?o where {?s ?p ?o} limit 10
   ```

# 使用 RDF4J Workbench 連線到 Neptune 資料庫執行個體
<a name="access-graph-sparql-rdf4j-workbench"></a>

本小節逐步引導您使用 RDF4J Workbench 和 RDF4J Server 連線到 Amazon Neptune 資料庫執行個體。RDF4J Server 是必要的，因為其做為 Neptune SPARQL HTTP REST 端點和 RDF4J Workbench 之間的 Proxy。

RDF4J Workbench 提供了簡單的介面以用來試驗圖形，包括可載入本機檔案。如需詳細資訊，請參閱 RDF4J 文件中的[新增區段](https://rdf4j.org/documentation/tools/server-workbench/#add)。

**先決條件**  
開始之前，請執行以下動作：
+ 安裝 Java 1.8 或更新版本。
+ 安裝 RDF4J Server 和 RDF4J Workbench。如需詳細資訊，請參閱[安裝 RDF4J Server 和 RDF4J Workbench](https://rdf4j.org/documentation/tools/server-workbench/#installing-rdf4j-server-and-rdf4j-workbench)。

**使用 RDF4J Workbench 連線到 Neptune**

1. 在 Web 瀏覽器中，導覽到部署 RDF4J Workbench Web 應用程式的 URL。例如，如果您使用 Apache Tomcat，URL：[https://*ec2\$1hostname*:8080/rdf4j-workbench/](http://localhost:8080/rdf4j-workbench/)。

1. 若系統要求您 **Connect to RDF4J Server (連接到 RDF4J 伺服器)**，請確認 **RDF4J 伺服器**已安裝並執行中，且伺服器 URL 正確無誤。接著繼續進行下一個步驟。

1. 在左側窗格中，選擇 **New repository** (新增儲存庫)。

   在 **New repository** (新增儲存庫) 中：
   + 在 **Type (類型)** 下拉式清單中，選擇 **SPARQL endpoint proxy (SPARQL 端點 Proxy)**。
   + 在 **ID** 中，輸入 **neptune**。
   + 針對**標題**，輸入 **Neptune 資料庫執行個體**。

   選擇**下一步**。

1. 在 **New repository** (新增儲存庫) 中：
   + 在 **SPARQL query endpoint URL (SPARQL 查詢端點 URL)** 中，輸入 `https://your-neptune-endpoint:port/sparql`。
   + 在 **SPARQL update endpoint URL (SPARQL 更新端點 URL)** 中，輸入 `https://your-neptune-endpoint:port/sparql`。

   如需尋找 Neptune 資料庫執行個體地址的相關資訊，請參閱 [連線至 Amazon Neptune 端點](feature-overview-endpoints.md) 一節。

   選擇**建立**。

1. **neptune** 儲存庫現在會顯示在儲存庫清單中。可能需要幾分鐘的時間才能使用新的儲存庫。

1. 在表格的 **Id** 欄中，選擇 **neptune** 連結。

1. 從左側窗格選擇 **Query** (查詢)。

    
**注意**  
如果 **Explore** (探索) 底下的功能表項目停用，您可能需要重新連線到 RDF4J 伺服器，並再次選擇 **neptune** 儲存庫。  
若要這樣做，您可以使用右上角的 **[change]** ([變更]) 連結。

1. 在查詢欄位中，輸入以下 SPARQL 查詢，然後選擇 **Execute** (執行)。

    

   ```
   select ?s ?p ?o where {?s ?p ?o} limit 10
   ```

    

先前範例使用 `?s ?p ?o` 查詢和限制 10，以傳回圖形中的最多 10 個三元組 (subject-predicate-object)。

# 使用 Java 連線至 Neptune 資料庫執行個體
<a name="access-graph-sparql-java"></a>

本節逐步引導您執行完整的 Java 範例，以連線到 Amazon Neptune 資料庫執行個體並執行 SPARQL 查詢。

請從與您的 Neptune 資料庫執行個體位於同一虛擬私有雲端 (VPC) 的 Amazon EC2 執行個體依照以下指示進行。

**使用 Java 連線至 Neptune**

1. 在 EC2 執行個體上安裝 Apache Maven。如果使用 Amazon Linux 2023 （偏好），請使用：

   ```
   sudo dnf update -y
   sudo dnf install maven -y
   ```

   如果使用 Amazon Linux 2，請從 [https://maven.apache.org/download.cgi：// 下載最新的二進位檔： ](https://maven.apache.org/download.cgi:)

   ```
   sudo yum remove maven -y
   wget https://dlcdn.apache.org/maven/maven-3/ <version>/binaries/apache-maven-<version>-bin.tar.gz
   sudo tar -xzf apache-maven-<version>-bin.tar.gz -C /opt/
   sudo ln -sf /opt/apache-maven-<version> /opt/maven
   echo 'export MAVEN_HOME=/opt/maven' >> ~/.bashrc
   echo 'export PATH=$MAVEN_HOME/bin:$PATH' >> ~/.bashrc
   source ~/.bashrc
   ```

1. 本範例僅經過 Java 8 的測試。輸入以下內容將 Java 8 安裝在 EC2 執行個體上：

   ```
   sudo yum install java-1.8.0-devel
   ```

1. 輸入以下內容將 Java 8 設定為 EC2 執行個體上預設的執行時間：

   ```
   sudo /usr/sbin/alternatives --config java
   ```

   出現提示時，輸入 Java 8 的數字。

1. 輸入以下內容將 Java 8 設定為 EC2 執行個體上預設的編譯器：

   ```
   sudo /usr/sbin/alternatives --config javac
   ```

   出現提示時，輸入 Java 8 的數字。

1. 在新目錄中，建立一個 `pom.xml` 檔案，然後在文字編輯器中開啟檔案。

1. 將以下內容複製到 `pom.xml` 檔案中並儲存它 (您通常可以將版本編號調整為最新的穩定版本)：

   ```
   <project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.amazonaws</groupId>
     <artifactId>RDFExample</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>RDFExample</name>
     <url>https://maven.apache.org</url>
     <dependencies>
       <dependency>
         <groupId>org.eclipse.rdf4j</groupId>
         <artifactId>rdf4j-runtime</artifactId>
         <version>3.6</version>
       </dependency>
     </dependencies>
     <build>
       <plugins>
         <plugin>
             <groupId>org.codehaus.mojo</groupId>
             <artifactId>exec-maven-plugin</artifactId>
             <version>1.2.1</version>
             <configuration>
               <mainClass>com.amazonaws.App</mainClass>
             </configuration>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <configuration>
             <source>1.8</source>
             <target>1.8</target>
           </configuration>
         </plugin>
       </plugins>
     </build>
   </project>
   ```
**注意**  
如果您要修改現有的 Maven 專案，所需的相依性將在先前的程式碼中反白顯示。

1. 若要為範例來源碼 (`src/main/java/com/amazonaws/`) 建立子目錄，請在命令列輸入下列命令：

   ```
   mkdir -p src/main/java/com/amazonaws/
   ```

1. 在 `src/main/java/com/amazonaws/` 目錄中，建立一個名為 `App.java` 的檔案，然後在文字編輯器中開啟檔案。

1. 將以下內容複製到 `App.java` 檔案。將 *your-neptune-endpoint* 取代為 Neptune 資料庫執行個體的地址。
**注意**  
如需尋找 Neptune 資料庫執行個體主機名稱的相關資訊，請參閱 [連線至 Amazon Neptune 端點](feature-overview-endpoints.md) 一節。

   ```
   package com.amazonaws;
   
   import org.eclipse.rdf4j.repository.Repository;
   import org.eclipse.rdf4j.repository.http.HTTPRepository;
   import org.eclipse.rdf4j.repository.sparql.SPARQLRepository;
   
   import java.util.List;
   import org.eclipse.rdf4j.RDF4JException;
   import org.eclipse.rdf4j.repository.RepositoryConnection;
   import org.eclipse.rdf4j.query.TupleQuery;
   import org.eclipse.rdf4j.query.TupleQueryResult;
   import org.eclipse.rdf4j.query.BindingSet;
   import org.eclipse.rdf4j.query.QueryLanguage;
   import org.eclipse.rdf4j.model.Value;
   
   public class App
   {
       public static void main( String[] args )
       {
           String sparqlEndpoint = "https://your-neptune-endpoint:port/sparql";
           Repository repo = new SPARQLRepository(sparqlEndpoint);
           repo.initialize();
   
           try (RepositoryConnection conn = repo.getConnection()) {
              String queryString = "SELECT ?s ?p ?o WHERE { ?s ?p ?o } limit 10";
   
              TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
   
              try (TupleQueryResult result = tupleQuery.evaluate()) {
                 while (result.hasNext()) {  // iterate over the result
                      BindingSet bindingSet = result.next();
   
                      Value s = bindingSet.getValue("s");
                      Value p = bindingSet.getValue("p");
                      Value o = bindingSet.getValue("o");
   
                      System.out.print(s);
                      System.out.print("\t");
                      System.out.print(p);
                      System.out.print("\t");
                      System.out.println(o);
                 }
              }
           }
       }
   }
   ```

1. 使用下列 Maven 命令編譯並執行範例：

   ```
   mvn compile exec:java
   ```

先前範例使用 `?s ?p ?o` 查詢和限制 10，以傳回圖形中的最多 10 個三元組 (subject-predicate-object)。若要查詢其他項目，請將查詢換成其他 SPARQL 查詢。

範例中重複出現的結果將印出所傳回之各變數的值。`Value` 物件會轉換成 `String`，然後列印。如果您變更查詢的 `SELECT` 部分，您必須修改程式碼。

# SPARQL HTTP API
<a name="sparql-api-reference"></a>

SPARQL HTTP 請求在以下端點接受：`https://your-neptune-endpoint:port/sparql`

如需使用 SPARQL 連線到 Amazon Neptune 的詳細資訊，請參閱 [使用 SPARQL 存取 Neptune 圖形](access-graph-sparql.md)。

如需 SPARQL 通訊協定和查詢語言的詳細資訊，請參閱 [SPARQL 1.1 通訊協定](https://www.w3.org/TR/sparql11-protocol/#protocol)和 [SPARQL 1.1 查詢語言](https://www.w3.org/TR/sparql11-query/)規格。

下列主題提供 SPARQL RDF 序列化格式，以及如何搭配 Neptune 使用 SPARQL HTTP API 的相關資訊。

**Contents**
+ [

# 使用 HTTP REST 端點連線到 Neptune 資料庫執行個體
](access-graph-sparql-http-rest.md)
+ [

# 用於多部分 SPARQL 回應的選用 HTTP 結尾標頭
](access-graph-sparql-http-trailing-headers.md)
+ [

# SPARQL 在 Neptune 中使用的 RDF 媒體類型
](sparql-media-type-support.md)
  + [

## Neptune SPARQL 使用的 RDF 序列化格式
](sparql-media-type-support.md#sparql-serialization-formats)
  + [

## Neptune SPARQL 使用的 SPARQL 結果序列化格式
](sparql-media-type-support.md#sparql-serialization-formats-neptune-output)
  + [

## Neptune 可用來匯入 RDF 資料的媒體類型
](sparql-media-type-support.md#sparql-serialization-formats-input)
  + [

## Neptune 可用來匯出查詢結果的媒體類型
](sparql-media-type-support.md#sparql-serialization-formats-output)
+ [

# 使用 SPARQL UPDATE LOAD 將資料匯入至 Neptune
](sparql-api-reference-update-load.md)
+ [

# 使用 SPARQL UPDATE UNLOAD 從 Neptune 刪除資料
](sparql-api-reference-unload.md)

# 使用 HTTP REST 端點連線到 Neptune 資料庫執行個體
<a name="access-graph-sparql-http-rest"></a>

**注意**  
Neptune 目前不支援 HTTP/2 for REST API 請求。連接到端點時，用戶端必須使用 HTTP/1.1。

以下說明引導您使用 **curl** 命令、透過 HTTPS 連線和使用 HTTP 語法連線到 SPARQL 端點。請從與您的 Neptune 資料庫執行個體位於同一虛擬私有雲端 (VPC) 的 Amazon EC2 執行個體依照以下指示進行。

對 Neptune 資料庫執行個體進行 SPARQL 查詢時所用的 HTTP 端點為：`https://your-neptune-endpoint:port/sparql`。

**注意**  
如需尋找 Neptune 資料庫執行個體主機名稱的相關資訊，請參閱 [連線至 Amazon Neptune 端點](feature-overview-endpoints.md) 一節。

Amazon Neptune 會提供 HTTP 端點進行 SPARQL 查詢。REST 介面相容於 SPARQL 1.1 版。

**使用 HTTP POST 執行 QUERY**  
以下範例使用 **curl** 透過 HTTP **POST** 提交 SPARQL **`QUERY`**。

```
curl -X POST --data-binary 'query=select ?s ?p ?o where {?s ?p ?o} limit 10' https://your-neptune-endpoint:port/sparql
```

先前範例使用 `?s ?p ?o` 查詢和限制 10，以傳回圖形中的最多 10 個三元組 (subject-predicate-object)。若要查詢其他項目，請將查詢換成其他 SPARQL 查詢。

**注意**  
`SELECT` 和 `ASK` 查詢的回應預設 MIME 類型為 `application/sparql-results+json`。  
`CONSTRUCT` 和 `DESCRIBE` 查詢回應的預設 MIME 類型為 `application/n-quads`。  
如需 Neptune 用於序列化的媒體類型清單，請參閱 [Neptune SPARQL 使用的 RDF 序列化格式](sparql-media-type-support.md#sparql-serialization-formats)。

**使用 HTTP POST 執行 UPDATE**  
以下範例使用 **curl** 透過 HTTP **POST** 提交 SPARQL **`UPDATE`**。

```
curl -X POST --data-binary 'update=INSERT DATA { <https://test.com/s> <https://test.com/p> <https://test.com/o> . }' https://your-neptune-endpoint:port/sparql
```

上述範例插入以下三元組到 SPARQL 預設圖形：`<https://test.com/s> <https://test.com/p> <https://test.com/o>`

# 用於多部分 SPARQL 回應的選用 HTTP 結尾標頭
<a name="access-graph-sparql-http-trailing-headers"></a>

通常會以多個部分或區塊傳回 SPARQL 查詢和更新的 HTTP 回應。很難診斷在查詢或更新開始傳送這些區塊之後發生的失敗，特別是因為第一個區塊到達時，其 HTTP 狀態碼為 `200`。

除非您明確請求結尾標頭，否則 Neptune 只會透過將錯誤訊息附加到訊息本文 (通常已損毀) 來報告此類失敗。

若要使偵測和診斷此類問題更容易進行，您可以在請求中包括傳輸編碼 (TE) 結尾標頭 (`te: trailers`) (例如，請參閱[有關 TE 請求標頭的 MDN 頁面](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE))。這樣做會導致 Neptune 在回應區塊的結尾標頭內包括兩個新的標頭欄位：
+ `X-Neptune-Status` – 包含回應碼，後面接著簡短名稱。例如，若成功，結尾標頭將是：`X-Neptune-Status: 200 OK`。若失敗，回應代碼將是 [Neptune 引擎錯誤代碼](errors-engine-codes.md)，例如 `X-Neptune-Status: 500 TimeLimitExceededException`。
+ `X-Neptune-Detail` – 對於成功的請求而言是空的。若發生錯誤，它會包含 JSON 錯誤訊息。由於 HTTP 標頭值中只允許 ASCII 字元，因此 JSON 字串會進行 URL 編碼。錯誤訊息仍會附加至回應訊息本文。

# SPARQL 在 Neptune 中使用的 RDF 媒體類型
<a name="sparql-media-type-support"></a>

資源描述架構 (RDF) 資料可以多種不同方法序列化，大部分都能為 SPARQL 取用或輸出：

## Neptune SPARQL 使用的 RDF 序列化格式
<a name="sparql-serialization-formats"></a>
+ **RDF/XML** – RDF 的 XML 序列化，以 [RDF 1.1 XML 語法](https://www.w3.org/TR/rdf-syntax-grammar/)定義。媒體類型：`application/rdf+xml`。一般副檔名：`.rdf`。
+ **N-Triples** – 以行為基礎的純文字格式編碼 RDF 圖形，以 [RDF 1.1 N-Triples](https://www.w3.org/TR/n-triples/) 定義。媒體類型：`application/n-triples`、`text/turtle` 或 `text/plain`。一般副檔名：`.nt`。
+ **N-Quads** – 以行為基礎的純文字格式編碼 RDF 圖形，以 [RDF 1.1 N-Quads](https://www.w3.org/TR/n-quads/) 定義。這是 N-Triples 的延伸。媒體類型：`application/n-quads`，若使用 7 位元 US-ASCII 編碼，則為 `text/x-nquads`。一般副檔名：`.nq`。
+ **Turtle** – 以 [RDF 1.1 Turtle](https://www.w3.org/TR/turtle/) 定義的 RDF 文字語法，使用精簡而自然的文字型式，搭配常見使用模式和資料類型的縮寫，完整編寫 RDF 圖形。Turtle 使用 N-Triples 及 SPARQL 三元組模式語法提供多層次的相容性。媒體類型：`text/turtle`一般副檔名：`.ttl`。
+ **TriG** – 以 [RDF 1.1 TriG](https://www.w3.org/TR/trig/) 定義的 RDF 文字語法，使用精簡而自然的文字型式，搭配常見使用模式和資料類型的縮寫，完整編寫 RDF 圖形。TriG 是 Turtle 格式的延伸。媒體類型：`application/trig`。一般副檔名：`.trig`。
+ **N3 (Notation3)** – 以 [Notation3 (N3)：可閱讀的 RDF 語法](https://www.w3.org/TeamSubmission/n3/)定義的宣告和邏輯語言。N3 透過新增方程式 (為圖表本身的常值)、變數、邏輯暗示和功能述詞，擴充 RDF 資料模型，並提供 RDF/XML 的文字語法替代方案。媒體類型：`text/n3`。一般副檔名：`.n3`。
+ **JSON-LD** – 以 [JSON-LD 1.0](https://www.w3.org/TR/json-ld/) 定義的資料序列化和簡訊格式。媒體類型：`application/ld+json`。一般副檔名：`.jsonld`。
+ **TriX** – XML 中的 RDF 序列化，以 [TriX：XML 中的 RDF 三元組](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html)定義。媒體類型：`application/trix`。一般副檔名：`.trix`。
+ **SPARQL JSON 結果** – 使用 [SPARQL 1.1 查詢結果 JSON 格式](https://www.w3.org/TR/sparql11-results-json)的 RDF 序列化。媒體類型：`application/sparql-results+json`。一般副檔名：`.srj`。
+ **RDF4J 二進位格式** – 編碼 RDF 資料的二進位格式，以 [RDF4J 二進位 RDF 格式](https://rdf4j.org/documentation/reference/rdf4j-binary)記錄。媒體類型：`application/x-binary-rdf`。

## Neptune SPARQL 使用的 SPARQL 結果序列化格式
<a name="sparql-serialization-formats-neptune-output"></a>
+ **SPARQL XML 結果** – SPARQL 查詢語言提供的變數繫結 XML 格式和布林值結果格式，以 [SPARQL 查詢結果 XML 格式 (第 2 版)](https://www.w3.org/TR/rdf-sparql-XMLres/) 定義。媒體類型：`application/sparql-results+xml`。一般副檔名：`.srx`。
+ **SPARQL CSV 和 TSV 結果** – 使用逗號分隔值和定位字元分隔值來表達 `SELECT` 查詢的 SPARQL 查詢結果，以 [SPARQL 1.1 查詢結果 CSV 和 TSV 格式](https://www.w3.org/TR/sparql11-results-csv-tsv/)定義。媒體類型：逗號分隔值為 `text/csv`，定位字元分隔值為 `text/tab-separated-values`。一般副檔名：逗號分隔值為 `.csv`，定位字元分隔值為 `.tsv`。
+ **二進位結果表** – 編碼 SPARQL 查詢輸出的二進位格式。媒體類型：`application/x-binary-rdf-results-table`。
+ **SPARQL JSON 結果** – 使用 [SPARQL 1.1 查詢結果 JSON 格式](https://www.w3.org/TR/sparql11-results-json/)的 RDF 序列化。媒體類型：`application/sparql-results+json`。

## Neptune 可用來匯入 RDF 資料的媒體類型
<a name="sparql-serialization-formats-input"></a>

**[Neptune 大量載入器](bulk-load.md)支援的媒體類型**
+ [N-Triples](https://www.w3.org/TR/n-triples/)
+ [N-Quads](https://www.w3.org/TR/n-quads/)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [Turtle](https://www.w3.org/TR/turtle/)

**SPARQL UPDATE LOAD 可以匯入的媒體類型**
+ [N-Triples](https://www.w3.org/TR/n-triples/)
+ [N-Quads](https://www.w3.org/TR/n-quads/)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [Turtle](https://www.w3.org/TR/turtle/)
+ [TriG](https://www.w3.org/TR/trig/)
+ [N3](https://www.w3.org/TeamSubmission/n3/)
+ [JSON-LD](https://www.w3.org/TR/json-ld/)

## Neptune 可用來匯出查詢結果的媒體類型
<a name="sparql-serialization-formats-output"></a>

若要指定 SPARQL 查詢回應的輸出格式，請以查詢請求傳送 `"Accept: media-type"` 標頭。例如：

```
curl -H "Accept: application/nquads" ...
```

**SPARQL SELECT 可從 Neptune 輸出的 RDF 媒體類型**
+ [SPARQL JSON 結果](https://www.w3.org/TR/sparql11-results-json) (這是預設值)
+ [SPARQL XML 結果](https://www.w3.org/TR/rdf-sparql-XMLres/)
+ **二進位結果表** (媒體類型：`application/x-binary-rdf-results-table`)
+ [逗號分隔值 (CSV)](https://www.w3.org/TR/sparql11-results-csv-tsv/)
+ [定位字元分隔值 (TSV)](https://www.w3.org/TR/sparql11-results-csv-tsv/)

**SPARQL ASK 可從 Neptune 輸出的 RDF 媒體類型**
+ [SPARQL JSON 結果](https://www.w3.org/TR/sparql11-results-json) (這是預設值)
+ [SPARQL XML 結果](https://www.w3.org/TR/rdf-sparql-XMLres/)
+ **布林值** (媒體類型：`text/boolean`，表示 "true" 或 "false")

**SPARQL CONSTRUCT 可從 Neptune 輸出的 RDF 媒體類型**
+ [N-Quads](https://www.w3.org/TR/n-quads/) (這是預設值)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [JSON-LD](https://www.w3.org/TR/json-ld/)
+ [N-Triples](https://www.w3.org/TR/n-triples/)
+ [Turtle](https://www.w3.org/TR/turtle/)
+ [N3](https://www.w3.org/TeamSubmission/n3/)
+ [TriX](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html)
+ [TriG](https://www.w3.org/TR/trig/)
+ [SPARQL JSON 結果](https://www.w3.org/TR/sparql11-results-json)
+ [RDF4J 二進位 RDF 格式](https://rdf4j.org/documentation/reference/rdf4j-binary)

**SPARQL DESCRIBE 可從 Neptune 輸出的 RDF 媒體類型**
+ [N-Quads](https://www.w3.org/TR/n-quads/) (這是預設值)
+ [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/)
+ [JSON-LD](https://www.w3.org/TR/json-ld/)
+ [N-Triples](https://www.w3.org/TR/n-triples/)
+ [Turtle](https://www.w3.org/TR/turtle/)
+ [N3](https://www.w3.org/TeamSubmission/n3/)
+ [TriX](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html)
+ [TriG](https://www.w3.org/TR/trig/)
+ [SPARQL JSON 結果](https://www.w3.org/TR/sparql11-results-json)
+ [RDF4J 二進位 RDF 格式](https://rdf4j.org/documentation/reference/rdf4j-binary)

# 使用 SPARQL UPDATE LOAD 將資料匯入至 Neptune
<a name="sparql-api-reference-update-load"></a>

SPARQL UPDATE LOAD 命令的語法是在 [SPARQL 1.1 更新建議](https://www.w3.org/TR/sparql11-update/#load)中指定：

```
LOAD SILENT (URL of data to be loaded) INTO GRAPH (named graph into which to load the data)
```
+ **`SILENT`** – (*選用*) 即使在處理期間發生錯誤，也會導致操作傳回成功。

  這在單一交易包含多個陳述式 (例如，`"LOAD ...; LOAD ...; UNLOAD ...; LOAD ...;"`) 時很有用，而且即使某些遠端資料無法處理，您也想要交易完成。
+ *要載入的資料 URL* – (*必要*) 指定一個遠端資料檔案，其中包含要載入至圖形的資料。

  遠端檔案必須具有下列其中一個副檔名：
  + NTriples 為 `.nt`。
  + NQuads 為 `.nq`。
  + Trig 為 `.trig`。
  + RDF/XML 為 `.rdf`。
  + Turtle 為 `.ttl`。
  + N3 為 `.n3`。
  + JSON-LD 為 `.jsonld`。
+ **`INTO GRAPH`***(要載入資料的具名圖形)* – (*選用*) 指定應載入資料的圖形。

  Neptune 會將每個三元組與一個具名圖形建立關聯。您可以使用後援具名圖形 URI 來指定預設的具名圖形 (`http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`)，如下所示：

  ```
  INTO GRAPH <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph>
  ```

**注意**  
當您需要載入大量資料時，我們建議您使用 Neptune 大量載入器，而非 UPDATE LOAD。如需有關大量載入器的詳細資訊，請參閱 [使用 Amazon Neptune 大量載入器擷取資料](bulk-load.md)。

您可以使用 `SPARQL UPDATE LOAD` 直接從 Amazon S3 載入資料，或從取自於自我託管 Web 伺服器的檔案載入資料。要載入的資源必須和 Neptune 伺服器位於同一區域，而且 VPC 中必須允許資源的端點。如需建立 Amazon S3 端點的相關資訊，請參閱 [建立 Amazon S3 VPC 端點](bulk-load-data.md#bulk-load-prereqs-s3)。

所有 `SPARQL UPDATE LOAD` URI 都必須以 `https://` 開頭。這包括 Amazon S3 URL。

與 Neptune 大量載入器相反，呼叫 `SPARQL UPDATE LOAD` 是可完全交易的。

**使用 SPARQL UPDATE LOAD 直接從 Amazon S3 將檔案載入至 Neptune**

由於 Neptune 不允許您在使用 SPARQL UPDATLOAD 時將 IAM 角色傳遞給 Amazon S3，因此有問題的 Amazon S3 儲存貯體必須是公開的，或者您必須在 LOAD 查詢中使用[預先簽署的 Amazon S3 URL](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)。

若要產生 Amazon S3 檔案的預先簽章 URL，您可以使用如下所示的 AWS CLI 命令：

```
aws s3 presign --expires-in (number of seconds) s3://(bucket name)/(path to file of data to load)
```

然後，您可以在 `LOAD` 命令中使用產生的預先簽署 URL：

```
curl https://(a Neptune endpoint URL):8182/sparql \
  --data-urlencode 'update=load (pre-signed URL of the remote Amazon S3 file of data to be loaded) \
                           into graph (named graph)'
```

如需詳細資訊，請參閱[對請求進行身分驗證：使用查詢參數](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)。[Boto3 文件](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html)展示了如何使用 Python 指令碼來產生一個預先簽署的 URL。

此外，必須正確設定要載入的檔案內容類型。

1. 當您使用 `-metadata` 參數將檔案上傳至 Amazon S3 時，請設定檔案的內容類型，如下所示：

   ```
   aws s3 cp test.nt s3://bucket-name/my-plain-text-input/test.nt --metadata Content-Type=text/plain
   aws s3 cp test.rdf s3://bucket-name/my-rdf-input/test.rdf --metadata Content-Type=application/rdf+xml
   ```

1. 確認媒體類型資訊真實存在。執行：

   ```
   curl -v bucket-name/folder-name
   ```

   此命令的輸出應該顯示您在上傳檔案時所設定的媒體類型資訊。

1. 然後，您可以使用 `SPARQL UPDATE LOAD` 命令將這些檔案匯入至 Neptune：

   ```
   curl https://your-neptune-endpoint:port/sparql \
     -d "update=LOAD <https://s3.amazonaws.com/bucket-name/my-rdf-input/test.rdf>"
   ```

上述步驟僅適用於公有 Amazon S3 儲存貯體，或者您在 LOAD 查詢中使用[預先簽署 Amazon S3 URL](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) 存取的儲存貯體。

 您還可以設定一個 Web 代理服務器從私有 Amazon S3 儲存貯體，如下所示：

**搭配 SPARQL UPDATE LOAD 使用 Web 伺服器將檔案載入至 Neptune**

1. 在 VPC 內執行的電腦上安裝 Web 伺服器，此為要載入檔案的 VPC，且是 Neptune 託管所在。例如，使用 Amazon Linux，您可能會以下列方式安裝 Apache：

   ```
   sudo yum install httpd mod_ssl
   sudo /usr/sbin/apachectl start
   ```

1. 定義您要載入之 RDF 檔案內容的 MIME 類型。SPARQL 使用 Web 伺服器傳送的 `Content-type` 標頭來決定內容的輸入格式，所以您必須定義 Web 伺服器的相關 MIME 類型。

   例如，假設您使用以下副檔名來識別檔案格式：
   + NTriples 為 `.nt`。
   + NQuads 為 `.nq`。
   + Trig 為 `.trig`。
   + RDF/XML 為 `.rdf`。
   + Turtle 為 `.ttl`。
   + N3 為 `.n3`。
   + JSON-LD 為 `.jsonld`。

   如果您使用 Apache 2 做為 Web 伺服器，您要編輯檔案 `/etc/mime.types` 並新增以下類型：

   ```
    text/plain nt
    application/n-quads nq
    application/trig trig
    application/rdf+xml rdf
    application/x-turtle ttl
    text/rdf+n3 n3
    application/ld+json jsonld
   ```

1. 確認 MIME 類型映射有效。一旦啟動並執行 Web 伺服器，並以您選擇的格式託管 RDF 檔案，您就可以從本機主機向 Web 伺服器傳送請求，測試組態。

   例如，您可能會傳送類似以下的請求：

   ```
   curl -v http://localhost:80/test.rdf
   ```

   然後，在 `curl` 的詳細輸出中，您應該會看到如下一行：

   ```
   Content-Type: application/rdf+xml
   ```

   這會顯示已成功定義的內容類型映射。

1. 您現在可以使用 SPARQL UPDATE 命令載入資料：

   ```
   curl https://your-neptune-endpoint:port/sparql \
       -d "update=LOAD <http://web_server_private_ip:80/test.rdf>"
   ```

**注意**  
使用 `SPARQL UPDATE LOAD` 可以在載入大型來源檔案時於 Web 伺服器上觸發逾時。Neptune 會在檔案資料串流輸入的同時進行處理，對大型檔案而言，所需時間可能會比伺服器上設定的逾時時間長。這樣反而可能會造成伺服器關閉連線，當 Neptune 在串流中遇到未預期的 EOF 時，可能會導致下列錯誤訊息：  

```
{
  "detailedMessage":"Invalid syntax in the specified file",
  "code":"InvalidParameterException"
}
```
如果您收到此訊息，但不認為來源檔案包含無效的語法，請嘗試增加 Web 伺服器上的逾時時間設定。您也可以透過在伺服器上啟用偵錯日誌並尋找逾時時間來診斷問題。

# 使用 SPARQL UPDATE UNLOAD 從 Neptune 刪除資料
<a name="sparql-api-reference-unload"></a>

Neptune 也提供自訂 SPARQL 操作 (`UNLOAD`)，用於移除遠端來源中指定的資料。`UNLOAD` 可被視為 `LOAD` 操作的對應項。它的語法是：

```
UNLOAD SILENT (URL of the remote data to be unloaded) FROM GRAPH (named graph from which to remove the data)
```
+ **`SILENT`** – (*選用*) 即使在處理資料時發生錯誤，也會導致操作傳回成功。

  這在單一交易包含多個陳述式 (例如，`"LOAD ...; LOAD ...; UNLOAD ...; LOAD ...;"`) 時很有用，而且即使某些遠端資料無法處理，您也想要交易完成。
+ *要卸載的遠端資料 URL* – (*必要*) 指定一個遠端資料檔案，其中包含要從圖形卸載的資料。

  遠端檔案必須具有下列其中一個副檔名 (這些是 UPDATE-LOAD 支援的相同格式)：
  + NTriples 為 `.nt`。
  + NQuads 為 `.nq`。
  + Trig 為 `.trig`。
  + RDF/XML 為 `.rdf`。
  + Turtle 為 `.ttl`。
  + N3 為 `.n3`。
  + JSON-LD 為 `.jsonld`。

  `UNLOAD` 操作將會從您的資料庫叢集中移除此檔案包含的所有資料。

  任何 Amazon S3 身分驗證都必須包含在 URL 中，才能卸載資料。您可以預先簽署 Amazon S3 檔案，然後使用產生的 URL 安全地存取該檔案。例如：

  ```
  aws s3 presign --expires-in (number of seconds) s3://(bucket name)/(path to file of data to unload)
  ```

  然後：

  ```
  curl https://(a Neptune endpoint URL):8182/sparql \
    --data-urlencode 'update=unload (pre-signed URL of the remote Amazon S3 data to be unloaded) \
                             from graph (named graph)'
  ```

  如需詳細資訊，請參閱[對請求進行身分驗證：使用查詢參數](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)。
+ **`FROM GRAPH `***(要從中移除資料的具名圖形)* – (*選用*) 指定應從中卸載遠端資料的具名圖形。

  Neptune 會將每個三元組與一個具名圖形建立關聯。您可以使用後援具名圖形 URI 來指定預設的具名圖形 (`http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph`)，如下所示：

  ```
  FROM GRAPH <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph>
  ```

`UNLOAD` 會以 `LOAD` 對應至 `INSERT DATA { (inline data) }` 的相同方式對應至 `DELETE DATA { (inline data) }`。如同 `DELETE DATA`，`UNLOAD` 無法對包含空白節點的資料運作。

例如，如果本機 Web 伺服器提供名為 `data.nt` 的檔案，其中包含以下兩個三元組：

```
<http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#b> .
<http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#c> .
```

以下 `UNLOAD` 命令將從具名圖形 (`<http://example.org/graph1>`) 中刪除這兩個三元組：

```
UNLOAD <http://localhost:80/data.nt> FROM GRAPH <http://example.org/graph1>
```

這將與使用以下 `DELETE DATA` 命令具有相同的效果：

```
DELETE DATA {
  GRAPH <http://example.org/graph1> {
    <http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#b> .
    <http://example.org/resource#a> <http://example.org/resource#p> <http://example.org/resource#c> .
  }
}
```

**`UNLOAD` 命令擲回的例外狀況**
+ **`InvalidParameterException`** – 資料中有空白節點。*HTTP 狀態*：400 錯誤的請求。

  *訊息*：` Blank nodes are not allowed for UNLOAD`

   
+ **`InvalidParameterException`** – 資料中有不完整的語法。*HTTP 狀態*：400 錯誤的請求。

  *訊息*：`Invalid syntax in the specified file.`

   
+ **`UnloadUrlAccessDeniedException `** – 存取遭拒。*HTTP 狀態*：400 錯誤的請求。

  *訊息*：`Update failure: Endpoint (Neptune endpoint) reported access denied error. Please verify access.`

   
+ **`BadRequestException `** – 無法擷取遠端資料。*HTTP 狀態*：400 錯誤的請求。

  *訊息*：*(取決於 HTTP 回應)。*

# SPARQL 查詢提示
<a name="sparql-query-hints"></a>

您可以在 Amazon Neptune 中使用查詢提示來指定特定 SPARQL 查詢的最佳化和評估策略。

查詢提示使用在 SPARQL 查詢中嵌入的額外三重模式表示，包含以下部分：

```
scope hint value
```
+ *scope* – 決定查詢提示要套用到查詢的哪些部分，例如查詢中的特定群組或完整查詢。
+ *hint* – 識別要套用的提示類型。
+ *value* – 確定正在考慮的系統層面行為。

這些查詢提示和範圍會公開成為 Amazon Neptune 命名空間 `http://aws.amazon.com/neptune/vocab/v01/QueryHints#` 中的預先定義用語。本節範例包含命名空間做為 `hint` 前綴，此前綴己定義並包含在查詢中：

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

例如，以下說明如何在 `SELECT` 查詢中包含 `joinOrder` 提示：

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

上述查詢會指示 Neptune 引擎依「給定」**順序評估查詢中的聯結，並停用任何自動重新排序。

使用查詢提示時請考慮以下情況：
+ 您可以將不同的查詢提示合併在單一查詢中。例如，您可以使用 `bottomUp` 查詢提示來將子查詢標註為由下而上的評估，並使用 `joinOrder` 查詢提示來修復子查詢中的聯結順序。
+ 您可以在不同的非重疊範圍中，多次使用相同的查詢提示。
+ 查詢提示是提示。雖然查詢引擎通常的目標是要考慮給定的查詢提示，也可以予以忽略。
+ 查詢提示為語意保留。新增查詢提示不會變更查詢的輸出 (除了沒有提供排序保證時的可能結果順序 - 也就是沒有使用 ORDER BY 明確強制執行結果順序)。

以下章節提供 Neptune 中可用的查詢提示以及其用法的詳細資訊。

**Topics**
+ [

## Neptune 中的 SPARQL 查詢提示範圍
](#sparql-query-hints-scope)
+ [

# `joinOrder` SPARQL 查詢提示
](sparql-query-hints-joinOrder.md)
+ [

# `evaluationStrategy` SPARQL 查詢提示
](sparql-query-hints-evaluationStrategy.md)
+ [

# `queryTimeout` SPARQL 查詢提示
](sparql-query-hints-queryTimeout.md)
+ [

# `rangeSafe` SPARQL 查詢提示
](sparql-query-hints-rangeSafe.md)
+ [

# `queryId` SPARQL 查詢提示
](sparql-query-hints-queryId.md)
+ [

# `useDFE` SPARQL 查詢提示
](sparql-query-hints-useDFE.md)
+ [

# 與 DESCRIBE 搭配使用的 SPARQL 查詢提示
](sparql-query-hints-for-describe.md)

## Neptune 中的 SPARQL 查詢提示範圍
<a name="sparql-query-hints-scope"></a>

下表顯示 Amazon Neptune 中 SPARQL 查詢提示的可行範圍、相關聯的提示和說明。這些項目中的 `hint` 字首代表提示的 Neptune 命名空間：

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


| Scope (範圍) | 支援的提示 | Description | 
| --- | --- | --- | 
| hint:Query | [joinOrder](sparql-query-hints-joinOrder.md) | 查詢提示適用於整個查詢。 | 
| hint:Query | [queryTimeout](sparql-query-hints-queryTimeout.md) | 逾時值適用於整個查詢。 | 
| hint:Query | [rangeSafe](sparql-query-hints-rangeSafe.md) | 針對整個查詢停用類型提升。 | 
| hint:Query | [queryId](sparql-query-hints-queryId.md) | 查詢 ID 值適用於整個查詢。 | 
| hint:Query | [useDFE](sparql-query-hints-useDFE.md) | 已啟用 (或停用) 將 DFE 用於整個查詢。 | 
| hint:Group | [joinOrder](sparql-query-hints-joinOrder.md) | 查詢提示適用於指定群組中的最上層元素，但不適用於巢狀元素 (如子查詢) 或父元素。 | 
| hint:SubQuery | [evaluationStrategy](sparql-query-hints-evaluationStrategy.md) | 提示指定及套用到巢狀的 SELECT 子查詢。子查詢是獨立評估的，不會考慮在子查詢之前計算的解決方案。 | 

# `joinOrder` SPARQL 查詢提示
<a name="sparql-query-hints-joinOrder"></a>

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

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

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

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

## `joinOrder` SPARQL 提示語法
<a name="sparql-query-hints-joinOrder-syntax"></a>

`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 提示範例
<a name="sparql-query-hints-joinOrder-example"></a>

本節示範使用和不使用 `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 個) 雙人組。

# `evaluationStrategy` SPARQL 查詢提示
<a name="sparql-query-hints-evaluationStrategy"></a>

`evaluationStrategy` 查詢提示會告訴 Amazon Neptune 查詢引擎，應該將標註的查詢片段當做獨立單位由下而上評估。這表示之前評估步驟的解決方案不會用來計算查詢片段。查詢片段被當做獨立單位而評估，其生成的解決方案在計算後與查詢的其餘部分聯結。

使用 `evaluationStrategy` 查詢提示暗示區塊化 (非管道化的) 查詢計畫，這意味著使用查詢提示標註的片段解決方案，在主記憶體中會具體化和緩衝。使用此查詢提示可能會大幅增加評估查詢所需的主記憶體，尤其是在標註的查詢片段計算大量結果時。

## `evaluationStrategy` SPARQL 提示語法
<a name="sparql-query-hints-evaluationStrategy-syntax"></a>

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

為更清楚起見，以下語法使用已定義並包含在查詢中的 `hint` 字首，指定 Neptune 查詢提示命名空間：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
hint:SubQuery hint:evaluationStrategy "BottomUp" .
```

**可用範圍**
+ `hint:SubQuery`

**注意**  
只有巢狀子查詢支援此查詢提示。

如需更多查詢提示範圍的詳細資訊，請參閱 [Neptune 中的 SPARQL 查詢提示範圍](sparql-query-hints.md#sparql-query-hints-scope)。

## `evaluationStrategy` SPARQL 提示範例
<a name="sparql-query-hints-evaluationStrategy-example"></a>



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

此範例假設資料集有下列特性：
+ 包含 1,000 個有標記 `:connectedTo` 的邊緣。
+ 每個 `component` 節點平均連接到 100 個其他 `component` 節點。
+ 節點之間四躍點循環連接的數量通常是大約 100 個。

典型的範例是，`evaluationStrategy` 提示有助於最佳化包含循環的查詢模式。

**無查詢提示**  
以下 SPARQL 查詢會擷取透過四個躍點彼此循環連接的所有 `component` 節點：

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
  ?component1 :connectedTo ?component2 .
  ?component2 :connectedTo ?component3 .
  ?component3 :connectedTo ?component4 .
  ?component4 :connectedTo ?component1 .
}
```

Neptune 查詢引擎的做法是使用以下步驟評估此查詢：
+ 擷取圖中的全部 `connectedTo` 邊緣，共 1,000 個。
+ 擴大 100 倍 (從 component2 傳出的 `connectedTo` 邊緣數量)。

  中間結果：100,000 個節點。
+ 擴大 100 倍 (從 component3 傳出的 `connectedTo` 邊緣數量)。

  中間結果：10,000,000 個節點。
+ 掃描 10,000,000 個節點的循環結束。

這會得到串流查詢計畫，其主記憶體為不變數量。

**查詢提示和子查詢**  
您可能想要犧牲主記憶體空間換取加速運算。使用 `evaluationStrategy` 查詢提示重寫查詢，您可以強制引擎計算兩個較小、具體化子集的聯結。

```
PREFIX : <https://example.com/>
          PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
  {
    SELECT * WHERE {
      hint:SubQuery hint:evaluationStrategy "BottomUp" .
      ?component1 :connectedTo ?component2 .
      ?component2 :connectedTo ?component3 .
    }
  }
  {
    SELECT * WHERE {
      hint:SubQuery hint:evaluationStrategy "BottomUp" .
      ?component3 :connectedTo ?component4 .
      ?component4 :connectedTo ?component1 .
    }
  }
}
```

相較於反覆使用先前三重模式的結果做為即將發生模式的輸入時評估序列中的三重模式，`evaluationStrategy` 提示會使得兩個子查詢被獨立評估。兩種子查詢的中繼結果都是產生 100,000 個節點，然後聯結在一起形成最終輸出。

特別是，當您在較大的執行個體類型上執行 Neptune 時，將這兩個 100,000 子集臨時儲存在主記憶體中，會增加記憶體使用量，進而大幅加快評估速度。

# `queryTimeout` SPARQL 查詢提示
<a name="sparql-query-hints-queryTimeout"></a>

`queryTimeout` 查詢提示指定的逾時比資料庫參數群組中設定的 `neptune_query_timeout` 值短。

如果查詢因為此提示而終止，則會擲出 `TimeLimitExceededException`，並帶有 `Operation terminated (deadline exceeded)` 訊息。

## `queryTimeout` SPARQL 提示語法
<a name="sparql-query-hints-queryTimeout-syntax"></a>

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ... WHERE {
    hint:Query hint:queryTimeout 10 .
    # OR
    hint:Query hint:queryTimeout "10" .
    # OR
    hint:Query hint:queryTimeout "10"^^xsd:integer .
 ...
}
```

逾時值以毫秒表示。

逾時值必須小於資料庫參數群組中設定的 `neptune_query_timeout` 值。否則，會擲出 `MalformedQueryException` 例外狀況，並帶有 `Malformed query: Query hint 'queryTimeout' must be less than neptune_query_timeout DB Parameter Group` 訊息。

`queryTimeout` 查詢提示應該在主要查詢的 `WHERE` 子句中指定，或在其中一個子查詢的 `WHERE` 子句中指定，如下例所示。

它必須在所有查詢/子查詢和 SPARQL Updates 區段 (例如 INSERT 和 DELETE) 上設定一次。否則，會擲出 `MalformedQueryException` 例外狀況，並帶有 `Malformed query: Query hint 'queryTimeout' must be set only once` 訊息。

**可用範圍**

`queryTimeout` 提示可同時套用至 SPARQL 查詢和更新。
+ 在 SPARQL 查詢中，它可以出現在主要查詢或子查詢的 WHERE 子句中。
+ 在 SPARQL 更新中，可以在 INSERT、DELETE 或 WHERE 子句中設定。如果有多個更新子句，則只能在其中一個設定。

如需更多查詢提示範圍的詳細資訊，請參閱 [Neptune 中的 SPARQL 查詢提示範圍](sparql-query-hints.md#sparql-query-hints-scope)。

## `queryTimeout` SPARQL 提示範例
<a name="sparql-query-hints-queryTimeout-example"></a>

下例在 `UPDATE` 查詢的主要 `WHERE` 子句中使用 `hint:queryTimeout`：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
INSERT {
    ?s ?p ?o
} WHERE {
    hint:Query hint:queryTimeout 100 .
    ?s ?p ?o .
}
```

在此，`hint:queryTimeout` 位在子查詢的 `WHERE` 子句中：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
   ?s ?p ?o .
   {
      SELECT ?s WHERE {
         hint:Query hint:queryTimeout 100 .
         ?s ?p1 ?o1 .
      }
   }
}
```

# `rangeSafe` SPARQL 查詢提示
<a name="sparql-query-hints-rangeSafe"></a>

使用此查詢提示來關閉 SPARQL 查詢的類型提升。

當您提交其包含的 `FILTER` 超過數值或範圍的 SPARQL 查詢時，Neptune 查詢引擎通常必須在執行查詢時使用類型提升。這表示它必須檢查可以保留您正在篩選之值的每種類型的值。

例如，如果您要篩選等於 55 的值，則引擎必須尋找等於 55 的整數、等於 55L 的長整數、等於 55.0 的浮點數等等。每個類型提升都需要對儲存體進行額外查詢，這可能會導致明顯簡單的查詢需要非預期的長時間才能完成。

通常類型提升不是必要的，因為您事先知道只需要找到一個特定類型的值即可。若是這種情況，您可以使用 `rangeSafe` 查詢提示來關閉類型提升，以大幅加快查詢速度。

## `rangeSafe` SPARQL 提示語法
<a name="sparql-query-hints-rangeSafe-syntax"></a>

`rangeSafe` 查詢提示會採取 `true` 值來關閉類型提升。它也接受 `false` 值 (預設值)。

**範例。**以下範例展示如何在篩選 `o` 大於 1 的整數值時關閉類型提升：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * {
   ?s ?p ?o .
   hint:Prior hint:rangeSafe 'true' .
   FILTER (?o > '1'^^<http://www.w3.org/2001/XMLSchema#int>)
```

# `queryId` SPARQL 查詢提示
<a name="sparql-query-hints-queryId"></a>

使用此查詢提示，將您自己的 queryId 值指派給 SPARQL 查詢。

範例：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT * WHERE {
  hint:Query hint:queryId "4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47"
  {?s ?p ?o}}
```

您指派的值在 Neptune 資料庫的所有查詢中必須是唯一的。

# `useDFE` SPARQL 查詢提示
<a name="sparql-query-hints-useDFE"></a>

使用此查詢提示來啟用使用 DFE 執行查詢。根據預設，Neptune 不會在未將此查詢提示設定為 `true` 的情況下使用 DFE，因為 [neptune\$1dfe\$1query\$1engine](parameters.md#parameters-instance-parameters-neptune_dfe_query_engine) 執行個體參數預設為 `viaQueryHint`。如果將該執行個體參數設定為 `enabled`，則除了 `useDFE` 查詢提示設定為 `false` 的查詢以外，所有查詢都會使用 DFE 引擎。

啟用將 DFE 用於查詢的範例：

```
PREFIX : <https://example.com/>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>

SELECT ?john ?jane
{
  hint:Query hint:useDFE true .
  ?person1 :name "Jane" .
  ?person1 :likes ?person2 .
  ?person2 :name "John" .
  ?person2 :likes ?person1 .
}
```

# 與 DESCRIBE 搭配使用的 SPARQL 查詢提示
<a name="sparql-query-hints-for-describe"></a>

SPARQL `DESCRIBE` 查詢提供了一種請求資源描述的靈活機制。不過，SPARQL 規格並未定義 `DESCRIBE` 的精確語義。

從[引擎 1.2.0.2 版](engine-releases-1.2.0.2.md)開始，Neptune 支援適用於不同情況的數種不同 `DESCRIBE` 模式和演算法。

此範例資料集可協助說明不同的模式：

```
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix : <https://example.com/> .

:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JohnDoe :firstName "John" .
:JaneDoe :knows _:b1 .
_:b1 :knows :RichardRoe .

:RichardRoe :knows :JaneDoe .
:RichardRoe :firstName "Richard" .

_:s1 rdf:type rdf:Statement .
_:s1 rdf:subject :JaneDoe .
_:s1 rdf:predicate :knows .
_:s1 rdf:object :JohnDoe .
_:s1 :knowsFrom "Berlin" .

:ref_s2 rdf:type rdf:Statement .
:ref_s2 rdf:subject :JaneDoe .
:ref_s2 rdf:predicate :knows .
:ref_s2 rdf:object :JohnDoe .
:ref_s2 :knowsSince 1988 .
```

以下範例假設使用 SPARQL 查詢請求資源 `:JaneDoe` 的描述，如下所示：

```
DESCRIBE <https://example.com/JaneDoe>
```

## `describeMode` SPARQL 查詢提示
<a name="sparql-query-hints-describeMode"></a>

`hint:describeMode` SPARQL 查詢提示用來選取下列其中一種 Neptune 支援的 SPARQL `DESCRIBE` 模式：

### `ForwardOneStep` DESCRIBE 模式
<a name="sparql-query-hints-describeMode-ForwardOneStep"></a>

您可以使用如下的 `describeMode` 查詢提示調用 `ForwardOneStep` 模式：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "ForwardOneStep"
}
```

`ForwardOneStep` 模式只會傳回要描述之資源的屬性和正向連結。在範例情況下，這表示它傳回具有 `:JaneDoe` (要描述的資源) 的三元組做為主旨：

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b301990159 .
```

請注意，DESCRAPE 查詢可能會傳回具有空白節點的三元組 (例如 `_:b301990159`)，與輸入資料集相比，它們每次都有不同的 ID。

### `SymmetricOneStep` DESCRIBE 模式
<a name="sparql-query-hints-describeMode-SymmetricOneStep"></a>

如果您未提供查詢提示，則 `SymmetricOneStep` 是預設 DESCRIBE 模式。您也可以使用如下的 `describeMode` 查詢提示明確地調用它：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "SymmetricOneStep"
}
```

在 `SymmetricOneStep` 語義下，`DESCRIBE` 會傳回要描述之資源的屬性、正向連結和反向連結：

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b318767375 .

_:b318767631 rdf:subject :JaneDoe .

:RichardRoe :knows :JaneDoe .

:ref_s2 rdf:subject :JaneDoe .
```

### 簡潔界限描述 (`CBD`) DESCRIBE 模式
<a name="sparql-query-hints-describeMode-CBD"></a>

簡潔界限描述 (`CBD`) 模式是使用如下的 `describeMode` 查詢提示來調用的：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "CBD"
}
```

在 `CBD` 語義下，`DESCRIBE` 會傳回要描述之資源的簡潔界限描述 (如 [W3C 定義](http://www.w3.org/Submission/CBD))：

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b285212943 .
_:b285212943 :knows :RichardRoe .

_:b285213199 rdf:subject :JaneDoe .
_:b285213199 rdf:type rdf:Statement .
_:b285213199 rdf:predicate :knows .
_:b285213199 rdf:object :JohnDoe .
_:b285213199 :knowsFrom "Berlin" .

:ref_s2 rdf:subject :JaneDoe .
```

RDF 資源的簡潔界限描述 (也就是 RDF 圖形中的節點) 是以該節點為中心且可單獨的最小子圖形。實際上，這表示如果您將此圖形視為一棵樹，將指定的節點作為根，則沒有空白節點 (bnode) 作為該樹的葉子。由於 bnode 無法從外部處理或在後續查詢中使用，因此只瀏覽圖形從目前節點中尋找下一個單一跳轉，這是不夠的。您還必須前進足夠遠才能找到可以在後續查詢中使用的項目 (也就是說，bnode 以外的項目)。

#### 計算 CBD
<a name="sparql-query-hints-describeMode-CBD-computing"></a>

鑑於來源 RDF 圖形中的特定節點 (起始節點或根節點)，該節點的 CBD 計算方式如下：

1. 子圖形中包含了來源圖形中的所有陳述式，其中陳述式的「主旨」**是起始節點。

1. 遞迴地，對於子圖形中迄今為止具有空白節點「物件」**的所有陳述式，子圖形中包含了來源圖形中的所有陳述式，其中陳述式的「主旨」**是該空白節點，並且尚未包含在子圖形中。

1. 遞迴地，對於子圖形中迄今為止包含的所有陳述式，會針對來源圖形中這些陳述式的所有具體化，包括從每個具體化的 `rdf:Statement` 節點開始的 CBD。

這會產生一個子圖形，其中「物件」**節點是 IRI 參考或常值，或是不做為圖形中任何陳述式之「主旨」**的空白節點。請注意，無法使用單一 SPARQL SELECT 或 CONSTRUCT 查詢來計算 CBD。

### 對稱簡潔界限描述 (`SCBD`) DESCRIBE 模式
<a name="sparql-query-hints-describeMode-SCBD"></a>

對稱簡潔界限描述 (`SCBD`) 模式是使用如下的 `describeMode` 查詢提示來調用的：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE <https://example.com/JaneDoe>
{
  hint:Query hint:describeMode "SCBD"
}
```

在 `SCBD` 語義下，`DESCRIBE` 會傳回資源的對稱簡潔界限描述 (如 W3C 在[使用 VoID 詞彙描述連結的資料集](http://www.w3.org/TR/void/)中所定義)：

```
:JaneDoe :firstName "Jane" .
:JaneDoe :knows :JohnDoe .
:JaneDoe :knows _:b335544591 .
_:b335544591 :knows :RichardRoe .

:RichardRoe :knows :JaneDoe .

_:b335544847 rdf:subject :JaneDoe .
_:b335544847 rdf:type rdf:Statement .
_:b335544847 rdf:predicate :knows .
_:b335544847 rdf:object :JohnDoe .
_:b335544847 :knowsFrom "Berlin" .

:ref_s2 rdf:subject :JaneDoe .
```

CBD 和 SCBD 優於 `ForwardOneStep` 和 `SymmetricOneStep` 模式的地方是空白節點始終會擴展以包含其表示法。這可能是一個重要的優勢，因為您無法使用 SPARQL 查詢空白節點。此外，CBD 和 SCBD 模式還會考慮具體化。

請注意，`describeMode` 查詢提示也可以是 `WHERE` 子句的一部分：

```
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
DESCRIBE ?s
WHERE {
  hint:Query hint:describeMode "CBD" .
  ?s rdf:type <https://example.com/Person>
}
```

## `describeIterationLimit` SPARQL 查詢提示
<a name="sparql-query-hints-describeIterationLimit"></a>

`hint:describeIterationLimit` SPARQL 查詢提示會對迭代擴展次數上限提供**選用**限制，而這些擴展是針對迭代 DESCRIBE 演算法 (例如 CBD 和 SCBD) 所執行的。

DESCRIBE 限制是透過 AND 結合在一起。因此，如果同時指定了迭代限制和陳述式限制，則必須符合這兩個限制，然後才能切斷 DESCRIBE 查詢。

此值的預設值為 5。您可以將其設定為 ZERO (0)，對迭代擴展的次數指定無限制。

## `describeStatementLimit` SPARQL 查詢提示
<a name="sparql-query-hints-describeStatementLimit"></a>

`hint:describeStatementLimit` SPARQL 查詢提示會對 SHARECT 查詢回應中可能存在的陳述式數目上限提供「選用」****限制。它僅適用於迭代 DESCRIBE 演算法，例如 CBD 和 SCBD。

DESCRIBE 限制是透過 AND 結合在一起。因此，如果同時指定了迭代限制和陳述式限制，則必須符合這兩個限制，然後才能切斷 DESCRIBE 查詢。

此值的預設值為 5000。您可以將其設定為 ZERO (0)，對傳回的陳述式數目指定無限制。

# 關於預設圖形的 SPARQL DESCRIBE 行為
<a name="sparql-default-describe"></a>

SPARQL [https://www.w3.org/TR/sparql11-query/#describe](https://www.w3.org/TR/sparql11-query/#describe) 查詢表單可讓您擷取資源的相關資訊，而無需知道資料結構，也不必撰寫查詢。如何組合這些資訊留給 SPARQL 實作決定。Neptune 提供了[數個查詢提示](sparql-query-hints-for-describe.md)，調用不同的模式和演算法，供 `DESCRIBE` 使用。

在 Neptune 的實作中，無論模式為何，`DESCRIBE` 只會使用 [SPARQL 預設圖形](feature-sparql-compliance.md#sparql-default-graph)中存在的資料。這與 SPARQL 處理資料集的方式一致 (請參閱 SPARQL 規格中的[指定 RDF 資料集](https://www.w3.org/TR/sparql11-query/#specifyingDataset))。

在 Neptune 中，除非使用 `FROM` 和/或 `FROM NAMED` 子句指定特定的具名圖形，否則預設圖形會包含資料庫中所有具名圖形之聯集中的所有唯一三元組。Neptune 的所有 RDF 資料都儲存在具名圖形中。如果插入沒有具名圖形內容的三元組，Neptune 會將其儲存在指定的具名圖形 `http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph` 中。

當使用 `FROM` 子句指定一或多個具名圖形時，預設圖形是這些具名圖形中所有唯一三元組的聯集。如果沒有 `FROM` 子句，但有一個或多個 `FROM NAMED` 子句，則預設圖形是空的。

## SPARQL `DESCRIBE` 範例
<a name="sparql-default-describe-examples"></a>

請考慮下列資料：

```
PREFIX ex: <https://example.com/>

GRAPH ex:g1 {
    ex:s ex:p1 "a" .
    ex:s ex:p2 "c" .
}

GRAPH ex:g2 {
    ex:s ex:p3 "b" .
    ex:s ex:p2 "c" .
}

ex:s ex:p3 "d" .
```

對於此查詢：

```
PREFIX ex: <https://example.com/>
DESCRIBE ?s
FROM ex:g1
FROM NAMED ex:g2
WHERE {
  GRAPH ex:g2 { ?s ?p "b" . }
}
```

Neptune 會傳回：

```
ex:s ex:p1 "a" .
ex:s ex:p2 "c" .
```

在這裡，首先評估圖形模式 `GRAPH ex:g2 { ?s ?p "b" }`，這會導致 `?s` 的繫結，然後對預設圖形評估 `DESCRIBE` 部分，現在只是 `ex:g1`。

不過，對於此查詢：

```
PREFIX ex: <https://example.com/>
DESCRIBE ?s 
FROM NAMED ex:g1 
WHERE { 
  GRAPH ex:g1 { ?s ?p "a" . } 
}
```

Neptune 不會傳回任何內容，因為當 `FROM NAMED` 子句存在，而沒有任何 `FROM` 子句時，預設圖形是空的。

在以下查詢中，`DESCRIBE` 會在沒有 `FROM` 或 `FROM NAMED` 子句存在的情況下使用：

```
PREFIX ex: <https://example.com/>
DESCRIBE ?s 
WHERE { 
  GRAPH ex:g1 { ?s ?p "a" . } 
}
```

在此情況下，預設圖形是由資料庫中所有具名圖形之聯集中的所有唯一三元組成 (正式稱為 RDF 合併)，因此 Neptune 將傳回：

```
ex:s ex:p1 "a" . 
ex:s ex:p2 "c" . 
ex:s ex:p3 "b" .
ex:s ex:p3 "d" .
```

# SPARQL 查詢狀態 API
<a name="sparql-api-status"></a>

若要取得 SPARQL 查詢的狀態，請使用 HTTP `GET` 或 `POST` 向 `https://your-neptune-endpoint:port/sparql/status` 端點提出請求。

## SPARQL 查詢狀態請求參數
<a name="sparql-api-status-get-request"></a>

**queryId (選用)**  
執行中 SPARQL 查詢的 ID。只顯示指定查詢的狀態。

## SPARQL 查詢狀態回應語法
<a name="sparql-api-status-get-response-syntax"></a>

```
{
    "acceptedQueryCount": integer,
    "runningQueryCount": integer,
    "queries": [
      {
        "queryId":"guid",
        "queryEvalStats":
          {
            "subqueries": integer,
            "elapsed": integer,
            "cancelled": boolean
          },
        "queryString": "string"
      }
    ]
}
```

## SPARQL 查詢狀態回應值
<a name="sparql-api-status-get-response-values"></a>

**acceptedQueryCount**  
自上次重新啟動 Neptune引擎以來接受的查詢數目。

**runningQueryCount**  
目前執行中的 SPARQL 查詢數。

**queries**  
目前 SPARQL 查詢的清單。

**queryId**  
查詢的 GUID ID。Neptune 會自動將此 ID 值指派給每個查詢，或者您也可以指派自己的 ID (請參閱 [將自訂 ID 注入至 Neptune Gremlin 或 SPARQL 查詢](features-query-id.md))。

**queryEvalStats**  
此查詢的統計資訊。

**subqueries**  
此查詢中的子查詢數。

**elapsed**  
到目前為止查詢已執行的毫秒數。

**cancelled**  
True 表示查詢已取消。

**queryString**  
提交的查詢。

## SPARQL 查詢狀態範例
<a name="sparql-api-status-get-example"></a>

下面是使用 `curl` 和 HTTP `GET` 的狀態命令範例。

```
curl https://your-neptune-endpoint:port/sparql/status
```

此輸出會顯示單一執行中查詢。

```
{
    "acceptedQueryCount":9,
    "runningQueryCount":1,
    "queries": [
        {
            "queryId":"fb34cd3e-f37c-4d12-9cf2-03bb741bf54f",
            "queryEvalStats":
                {
                    "subqueries": 0,
                    "elapsed": 29256,
                    "cancelled": false
                },
            "queryString": "SELECT ?s ?p ?o WHERE {?s ?p ?o}"
        }
    ]
}
```

# SPARQL 查詢取消
<a name="sparql-api-status-cancel"></a>

若要取得 SPARQL 查詢的狀態，請使用 HTTP `GET` 或 `POST` 向 `https://your-neptune-endpoint:port/sparql/status` 端點提出請求。

## SPARQL 查詢取消請求參數
<a name="sparql-api-status-cancel-request"></a>

**cancelQuery**  
(必要) 告知狀態命令取消查詢。此參數不採用數值。

**queryId**  
(必要) 要取消之執行中 SPARQL 查詢的 ID。

**silent**  
(選用) 如果 `silent=true`，則執行中查詢會遭到取消，且 HTTP 回應代碼為 200。如果 `silent` 不存在或 `silent=false`，則會取消查詢並顯示 HTTP 500 狀態碼。

## SPARQL 查詢取消範例
<a name="sparql-api-status-cancel-example"></a>

**範例 1：描配 `silent=false` 進行取消**  
以下是使用狀態命令的範例，其使用 `curl` 搭配設定為 `false` 的 `silent` 參數來取消查詢：

```
curl https://your-neptune-endpoint:port/sparql/status \
  -d "cancelQuery" \
  -d "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47" \
  -d "silent=false"
```

除非查詢已啟動串流結果，否則取消的查詢隨後將傳回 HTTP 500 代碼，回應如下：

```
{
  "code": "CancelledByUserException",
  "requestId": "4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47",
  "detailedMessage": "Operation terminated (cancelled by user)"
}
```

如果查詢已傳回 HTTP 200 代碼 (OK)，且在取消之前已啟動串流結果，則逾時例外狀況資訊會傳送至一般輸出串流。

**範例 2：搭配 `silent=true` 進行取消**  
以下是與上述相同狀態命令的範例，但 `silent` 參數現在設定為 `true`：

```
curl https://your-neptune-endpoint:port/sparql/status \
  -d "cancelQuery" \
  -d "queryId=4d5c4fae-aa30-41cf-9e1f-91e6b7dd6f47" \
  -d "silent=true"
```

此命令會傳回與 `silent=false` 時相同的回應，但取消的查詢現在會傳回 HTTP 200 代碼，其回應如下：

```
{
  "head" : {
    "vars" : [ "s", "p", "o" ]
  },
  "results" : {
    "bindings" : [ ]
  }
}
```

# 在 Amazon Neptune 中使用 SPARQL 1.1 圖形存放區 HTTP 通訊協定 (GSP)
<a name="sparql-graph-store-protocol"></a>

在 [SPARQL 1.1 圖形存放區 HTTP 通訊協定](https://www.w3.org/TR/sparql11-http-rdf-update/)建議中，W3C 定義了用於管理 RDF 圖形的 HTTP 通訊協定。它會定義用於移除、建立和取代 RDF 圖形內容的操作，以及用於將 RDF 陳述式新增至現有內容的操作。

圖形存放區通訊協定 (GSP) 提供了一種便利的方式來操作您的整個圖形，而不必撰寫複雜的 SPARQL 查詢。

Neptune 完全支援此通訊協定。

圖形存放區通訊協定 (GSP) 的端點為：

```
https://your-neptune-cluster:port/sparql/gsp/
```

若要使用 GSP 存取預設圖形，請使用：

```
https://your-neptune-cluster:port/sparql/gsp/?default
```

若要使用 GSP 存取具名圖形，請使用：

```
https://your-neptune-cluster:port/sparql/gsp/?graph=named-graph-URI
```

## Neptune GSP 實作的特殊詳細資訊
<a name="sparql-graph-store-protocol-special"></a>

Neptune 完全實作了定義 GSP 的 [W3C 建議](https://www.w3.org/TR/sparql11-http-rdf-update/)。不過，有一些規格未涵蓋的情況。

其中一種情況是，`PUT` 或 `POST` 請求在請求內文中指定一個或多個具名圖形，這些圖形與請求 URL 指定的圖形不同。僅在請求內文 RDF 格式支援具名圖形時，才可能發生這種情況，例如，使用 `Content-Type: application/n-quads` 或 `Content-Type: application/trig`。

在此情況下，Neptune 會新增或更新內文中存在的所有具名圖形，以及在 URL 中指定的具名圖形。

例如，假設從空白資料庫開始，您會傳送 `PUT` 請求，以將選票 upsert 至三個圖形。其中一個名為 `urn:votes`，包含來自所有選舉年的所有選票。另外兩個名為 `urn:votes:2005` 和 `urn:votes:2019`，包含來自特定選舉年的選票. 請求及其承載看起來像這樣：

```
PUT "http://your-Neptune-cluster:port/sparql/gsp/?graph=urn:votes"
  Host: example.com
  Content-Type: application/n-quads

  PAYLOAD:

  <urn:JohnDoe> <urn:votedFor> <urn:Labour> <urn:votes:2005>
  <urn:JohnDoe> <urn:votedFor> <urn:Conservative> <urn:votes:2019>
  <urn:JaneSmith> <urn:votedFor> <urn:LiberalDemocrats> <urn:votes:2005>
  <urn:JaneSmith> <urn:votedFor> <urn:Conservative> <urn:votes:2019>
```

在執行請求之後，資料庫中的資料看起來像這樣：

```
<urn:JohnDoe>   <urn:votedFor> <urn:Labour>           <urn:votes:2005>
<urn:JohnDoe>   <urn:votedFor> <urn:Conservative>     <urn:votes:2019>
<urn:JaneSmith> <urn:votedFor> <urn:LiberalDemocrats> <urn:votes:2005>
<urn:JaneSmith> <urn:votedFor> <urn:Conservative>     <urn:votes:2019>
<urn:JohnDoe>   <urn:votedFor> <urn:Labour>           <urn:votes>
<urn:JohnDoe>   <urn:votedFor> <urn:Conservative>     <urn:votes>
<urn:JaneSmith> <urn:votedFor> <urn:LiberalDemocrats> <urn:votes>
<urn:JaneSmith> <urn:votedFor> <urn:Conservative>     <urn:votes>
```

另一個不明確的情況是，在請求 URL 本身中使用任一 `PUT`、`POST`、`GET` 或 `DELETE` 指定多個圖形 例如：

```
POST "http://your-Neptune-cluster:port/sparql/gsp/?graph=urn:votes:2005&graph=urn:votes:2019"
```

或者：

```
GET "http://your-Neptune-cluster:port/sparql/gsp/?default&graph=urn:votes:2019"
```

在此情況下，Neptune 會傳回 HTTP 400，其中訊息指出只能在請求 URL 中指定一個圖形。

# 使用 SPARQL `explain` 分析 Neptune 查詢執行
<a name="sparql-explain"></a>

Amazon Neptune 已新增名為 *explain* 的 SPARQL 功能。這個功能是自助式工具，用於了解 Neptune 引擎採取的執行方法。您透過將 `explain` 參數新增到提交 SPARQL 查詢的 HTTP 呼叫，來進行叫用。

此 `explain` 功能可提供查詢執行計劃邏輯結構的相關資訊。您可以使用此資訊來識別潛在的評估和執行瓶頸。然後，您可以使用[查詢提示](sparql-query-hints.md)，以改善您的查詢執行計劃。

**Topics**
+ [

# SPARQL 查詢引擎在 Neptune 的運作方式
](sparql-explain-engine.md)
+ [

# 如何使用 SPARQL `explain` 來分析 Neptune 查詢執行
](sparql-explain-using.md)
+ [

# 在 `explain` 中調用 SPARQL 的範例
](sparql-explain-examples.md)
+ [

# Neptune SPARQL `explain` 運算子
](sparql-explain-operators.md)
+ [

# Neptune 中 SPARQL `explain` 的限制
](sparql-explain-limitations.md)

# SPARQL 查詢引擎在 Neptune 的運作方式
<a name="sparql-explain-engine"></a>

若要使用 SPARQL `explain` 功能提供的資訊，您需要了解一些 Amazon Neptune SPARQL 查詢引擎運作方式的詳細資訊。

此引擎會將每個 SPARQL 查詢轉換為運算子管道。從第一個運算子開始，名為*繫結清單*的中繼解決方案將套用至此運算子管道。您可以將繫結清單視為資料表，其中資料表標頭是查詢中所用的部分變數。因此，資料表中的每一列代表評估時間點之前的結果。

假設系統已為我們的資料定義兩個命名空間前綴：

```
  @prefix ex:   <http://example.com> .
  @prefix foaf: <http://xmlns.com/foaf/0.1/> .
```

以下是此內容中簡單繫結清單的範例：

```
  ?person       | ?firstName
  ------------------------------------------------------
  ex:JaneDoe    | "Jane"
  ex:JohnDoe    | "John"
  ex:RichardRoe | "Richard"
```

對於三個人中的每一個人，清單會將 `?person` 變數繫結至該人員的識別符，且將 `?firstName` 變數繫結至該人員的名字。

一般情況下，變數可以維持在未繫結的狀態，例如，對於資料中不存在值的查詢中變數的 `OPTIONAL` 選項。

`PipelineJoin` 運算子是 `explain` 輸出中存在 Neptune 查詢引擎運算子的範例。它會將輸入做為上個運算子的傳入繫結集，並針對三重模式來進行聯結，也就是 `(?person, foaf:lastName, ?lastName)`。這個運算子會在此輸入串流使用 `?person` 變數的繫結，將這些繫結取代為三重模式，並從資料庫中查詢三元素。

當從上個資料表中在傳入繫結內容中執行時，`PipelineJoin` 會評估三個查詢，也就是下列項目：

```
  (ex:JaneDoe,    foaf:lastName, ?lastName)
  (ex:JohnDoe,    foaf:lastName, ?lastName)
  (ex:RichardRoe, foaf:lastName, ?lastName)
```

這種方法稱為 *as-bound* 評估。系統會根據傳入解決方案重新聯結這個評估程序的解決方案，並在傳入解決方案中填補偵測到的 `?lastName`。假設您找到所有三個人員的姓氏，運算子會產生一個傳出繫結清單，這會像下面這樣：

```
  ?person       | ?firstName | ?lastName
  ---------------------------------------
  ex:JaneDoe    | "Jane"     | "Doe"
  ex:JohnDoe    | "John"     | "Doe"
  ex:RichardRoe | "Richard"  | "Roe"
```

這個傳出繫結清單則做為輸入，供管道中下一個運算子使用。最後，管道中最後一個運算子的輸出會定義查詢結果。

運算子管道通常是線性的，這是因為每個運算子會為單一連線的運算子發出解決方案。不過，在某些情況下，他們可以擁有更為複雜的結構。例如，SPARQL 查詢中的 `UNION` 運算子會映射到 `Copy` 操作。這個操作會複製繫結並將副本轉送到兩個子計劃，一個用於 `UNION` 的左側而另一個用於右側。

如需運算子的詳細資訊，請參閱 [Neptune SPARQL `explain` 運算子](sparql-explain-operators.md)。

# 如何使用 SPARQL `explain` 來分析 Neptune 查詢執行
<a name="sparql-explain-using"></a>

SPARQL `explain` 功能是 Amazon Neptune 中的自助式工具，可協助您了解 Neptune 引擎採取的執行方法。若要叫用 `explain`，您會以 `explain=mode` 的形式將參數傳遞到 HTTP 或 HTTPS 請求。

模式值可以是 `static` `dynamic` 或 `details` 的其中之一。
+ 在*靜態*模式中，`explain` 只會列印查詢計劃的靜態結構。
+ 在*動態*模式中，`explain` 還包括查詢計劃的動態層面。這些層面可能包含經由運算子流動的中繼繫結數和傳入繫結與傳出繫結的比率，以及運算子所耗費的時間。
+ 在*詳細資訊*模式中，`explain` 會列印 `dynamic` 模式中顯示的資訊及其他詳細資訊，例如，實際 SPARQL 查詢字串，以及構成聯結運算子基礎之模式的預估範圍計數。

Neptune 支援使用 `explain`，搭配在 [W3C SPARQL 1.1 通訊協定規格](https://www.w3.org/TR/sparql11-protocol/#query-operation)中所列的所有三個 SPARQL 查詢存取通訊協定，即：

1. HTTP GET

1. 使用 URL 編碼參數的 HTTP POST

1. 使用文字參數的 HTTP POST

如需 SPARQL 查詢引擎的詳細資訊，請參閱 [SPARQL 查詢引擎在 Neptune 的運作方式](sparql-explain-engine.md)。

如需叫用 SPARQL `explain` 產生之輸出種類的詳細資訊，請參閱 [在 `explain` 中調用 SPARQL 的範例](sparql-explain-examples.md)。

# 在 `explain` 中調用 SPARQL 的範例
<a name="sparql-explain-examples"></a>

本區段中的範例示範您透過調用 SPARQL `explain` 功能，在 Amazon Neptune 中分析查詢執行可以產生的各種輸出類型。

**Topics**
+ [

## 了解 Explain 輸出
](#sparql-explain-example-output)
+ [

## 詳細資訊模式輸出的範例
](#sparql-explain-example-details)
+ [

## 靜態模式輸出的範例
](#sparql-explain-example-static)
+ [

## 不同參數編碼方式
](#sparql-explain-example-parameters)
+ [

## 除了文字/純文字之外的其他輸出類型
](#sparql-explain-output-options)
+ [

## DFE 啟用時的 SPARQL `explain` 輸出範例
](#sparql-explain-output-dfe)

## 了解 Explain 輸出
<a name="sparql-explain-example-output"></a>

在這個範例中，Jane Doe 知道兩個人，也就是 John Doe 和 Richard Roe：

```
@prefix ex: <http://example.com> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

ex:JaneDoe foaf:knows ex:JohnDoe .
ex:JohnDoe foaf:firstName "John" .
ex:JohnDoe foaf:lastName "Doe" .
ex:JaneDoe foaf:knows ex:RichardRoe .
ex:RichardRoe foaf:firstName "Richard" .
ex:RichardRoe foaf:lastName "Roe" .
.
```

若要判斷 Jane Doe 知道的所有人的名字，您可以編寫以下查詢：

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -H "Accept: text/csv"
```

此簡單查詢會傳回下列結果：

```
firstName
John
Richard
```

接著，透過新增 `-d "explain=dynamic"` 和使用預設的輸出類型 (而不是 `text/csv`)，來變更 `curl` 命令以叫用 `explain`：

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -d "explain=dynamic"
```

查詢現在會在適合列印 ASCII 格式 (HTTP 內容類型 `text/plain`) (也就是預設的輸出類型) 中傳回輸出：

```
╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                             │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                        │ -        │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ PipelineJoin      │ pattern=distinct(ex:JaneDoe, foaf:knows, ?person)     │ -        │ 1        │ 2         │ 2.00  │ 1         ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person]                          │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ PipelineJoin      │ pattern=distinct(?person, foaf:firstName, ?firstName) │ -        │ 2        │ 2         │ 1.00  │ 1         ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person, ?firstName]              │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ Projection        │ vars=[?firstName]                                     │ retain   │ 2        │ 2         │ 1.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ -      │ -      │ TermResolution    │ vars=[?firstName]                                     │ id2value │ 2        │ 2         │ 1.00  │ 1         ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

對於在 `Name` 欄及其引數中的運算子詳細資訊，請參閱 [Explain 運算子](sparql-explain-operators.md)。

以下以逐列說明輸出：

1. 主要查詢的第一步一律是使用 `SolutionInjection` 運算子來注入解決方案。然後，系統會透過評估過程將解決方案擴展至最終結果。

   在這種情況下，它會注入所謂的通用解決方案 `{ }`。存在 `VALUES` 子句或 `BIND` 時，此步驟也可能注入更為複雜的變數繫結來開始使用。

   `Units Out` 欄表示這個單一解決方案會自此運算子傳出。`Out #1` 欄會指定此運算子將結果送入其中的運算子。在這個範例中，所有運算子會連接到此資料表中的以下運算子。

1. 第二個步驟是 `PipelineJoin`。它收到做為上個運算子 (`Units In := 1`) 產生的輸入單一 (完全無限制) 解決方案。並將其聯結至 `pattern` 引數定義的元組模式。此會對應到模式的簡單查詢。在這種情況下，會將三重模式定義為下列各項：

   ```
   distinct( ex:JaneDoe, foaf:knows, ?person )
   ```

   `joinType := join` 引數表示一般聯結操作 (其他類型包括 `optional` 聯結、`existence check` 聯結等)。

   `distinct := true` 引數表示您從資料庫 (非重複項目) 擷取的剛好是不同的符合項目，且您將不同的符合項目繫結至變數 `joinProjectionVars := ?person`，來去重複。

   事實上，`Units Out` 欄值為 2 表示有兩個傳出的解決方案。特別是，反映兩個人員的 `?person` 變數繫結，此資料說明 Jane Doe 知道：

   ```
    ?person
    -------------
    ex:JohnDoe
    ex:RichardRoe
   ```

1. 兩種解決方案從階段 2 流程做為輸入 (`Units In := 2`) 傳入至第二個 `PipelineJoin`。此運算子會將兩個舊解決方案與以下三重模式聯結：

   ```
   distinct(?person, foaf:firstName, ?firstName)
   ```

   已知運算子傳入解決方案會將 `?person` 變數繫結至 `ex:JohnDoe` 或 `ex:RichardRoe`。基於此，`PipelineJoin` 會擷取名字，John 和 Richard。兩個傳出解決方案 (Units Out := 2) 則如下所示：

   ```
    ?person       | ?firstName
    ---------------------------
    ex:JohnDoe    | John
    ex:RichardRoe | Richard
   ```

1. 下一個投影運算子使用階段 3 (`Units In := 2`) 兩個解決方案的輸入並投射到 `?firstName` 變數。這樣就不需在映射中繫結所有其他變數並在兩個繫結 (`Units Out := 2`) 上進行傳遞：

   ```
    ?firstName
    ----------
    John
    Richard
   ```

1. 為了改善效能，Neptune 會盡可能在其指派給 URI 和字串常值這類字詞的內部識別符上 (而不是在字串本身) 操作。最後一個運算子 `TermResolution` 會透過這些內部識別符執行映射，並傳回對應的字詞字串。

   在一般 (非說明) 查詢評估中，會將最後一個運算子運算的結果序列化為請求的序列化格式並串流到用戶端。

## 詳細資訊模式輸出的範例
<a name="sparql-explain-example-details"></a>

假設您執行的查詢與先前在*詳細資訊*模式 (而不是*動態*模式) 中執行的一樣：

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -d "explain=details"
```

如本範例所示，輸出與其他一些詳細資訊相同，例如，輸出頂端的查詢字串，以及 `PipelineJoin` 運算子的 `patternEstimate` 計數：

```
Query:
PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/>
SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }

╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                             │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                        │ -        │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ PipelineJoin      │ pattern=distinct(ex:JaneDoe, foaf:knows, ?person)     │ -        │ 1        │ 2         │ 2.00  │ 13        ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person]                          │          │          │           │       │           ║
║    │        │        │                   │ patternEstimate=2                                     │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ PipelineJoin      │ pattern=distinct(?person, foaf:firstName, ?firstName) │ -        │ 2        │ 2         │ 1.00  │ 3         ║
║    │        │        │                   │ joinType=join                                         │          │          │           │       │           ║
║    │        │        │                   │ joinProjectionVars=[?person, ?firstName]              │          │          │           │       │           ║
║    │        │        │                   │ patternEstimate=2                                     │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ Projection        │ vars=[?firstName]                                     │ retain   │ 2        │ 2         │ 1.00  │ 1         ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ -      │ -      │ TermResolution    │ vars=[?firstName]                                     │ id2value │ 2        │ 2         │ 1.00  │ 7         ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

## 靜態模式輸出的範例
<a name="sparql-explain-example-static"></a>

假設您執行的查詢與先前在*靜態*模式 (預設) (而不是*詳細資訊*模式) 中執行的一樣：

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=PREFIX foaf: <https://xmlns.com/foaf/0.1/> PREFIX ex: <https://www.example.com/> \
       SELECT ?firstName WHERE { ex:JaneDoe foaf:knows ?person . ?person foaf:firstName ?firstName }" \
   -d "explain=static"
```

如此範例所示，輸出都是相同的，但它省略最後三個欄位：

```
╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                             │ Mode     ║
╠════╪════════╪════════╪═══════════════════╪═══════════════════════════════════════════════════════╪══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                        │ -        ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 1  │ 2      │ -      │ PipelineJoin      │ pattern=distinct(ex:JaneDoe, foaf:knows, ?person)     │ -        ║
║    │        │        │                   │ joinType=join                                         │          ║
║    │        │        │                   │ joinProjectionVars=[?person]                          │          ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 2  │ 3      │ -      │ PipelineJoin      │ pattern=distinct(?person, foaf:firstName, ?firstName) │ -        ║
║    │        │        │                   │ joinType=join                                         │          ║
║    │        │        │                   │ joinProjectionVars=[?person, ?firstName]              │          ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 3  │ 4      │ -      │ Projection        │ vars=[?firstName]                                     │ retain   ║
╟────┼────────┼────────┼───────────────────┼───────────────────────────────────────────────────────┼──────────╢
║ 4  │ -      │ -      │ TermResolution    │ vars=[?firstName]                                     │ id2value ║
╚════╧════════╧════════╧═══════════════════╧═══════════════════════════════════════════════════════╧══════════╝
```

## 不同參數編碼方式
<a name="sparql-explain-example-parameters"></a>

以下範例查詢說明叫用 SPARQL `explain` 時兩種不同的參數編碼方法。

**使用 URL 編碼** – 此範例使用參數的 URL 編碼，並指定「動態」**輸出：

```
curl -XGET "http(s)://your_server:your_port/sparql?query=SELECT%20*%20WHERE%20%7B%20%3Fs%20%3Fp%20%3Fo%20%7D%20LIMIT%20%31&explain=dynamic"
```

**直接指定參數** – 與上個查詢相同，差別在於它直接透過 POST 來傳遞參數：

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=SELECT * WHERE { ?s ?p ?o } LIMIT 1" \
   -d "explain=dynamic"
```

## 除了文字/純文字之外的其他輸出類型
<a name="sparql-explain-output-options"></a>

上述範例使用預設 `text/plain` 輸出類型。Neptune 還可以透過其他兩種 MIME 類型格式 (即 `explain` 和 `text/csv`) 格式化 SPARQL `text/html` 輸出。您透過設定 HTTP `Accept` 標頭 (也就是您在 `curl` 使用 `-H` 旗標可以做的事) 來進行叫用，如下所示：

```
  -H "Accept: output type"
```

以下是一些範例：

**`text/csv` 輸出**  
此查詢透過指定 `-H "Accept: text/csv"` 來呼叫 CSV MIME 類型輸出：

```
 curl http(s)://your_server:your_port/sparql \
   -d "query=SELECT * WHERE { ?s ?p ?o } LIMIT 1" \
   -d "explain=dynamic" \
   -H "Accept: text/csv"
```

CSV 格式 (匯入到試算表或資料庫的實用格式)，透過分號 (`;`) 將每個 `explain` 列中的欄位分隔，如下所示：

```
ID;Out #1;Out #2;Name;Arguments;Mode;Units In;Units Out;Ratio;Time (ms)
0;1;-;SolutionInjection;solutions=[{}];-;0;1;0.00;0
1;2;-;PipelineJoin;pattern=distinct(?s, ?p, ?o),joinType=join,joinProjectionVars=[?s, ?p, ?o];-;1;6;6.00;1
2;3;-;Projection;vars=[?s, ?p, ?o];retain;6;6;1.00;2
3;-;-;Slice;limit=1;-;1;1;1.00;1
```

 

**`text/html` 輸出**  
如果您指定 `-H "Accept: text/html"`，則 `explain` 會產生 HTML 資料表：

```
<!DOCTYPE html>
<html>
  <body>
    <table border="1px">
      <thead>
        <tr>
          <th>ID</th>
          <th>Out #1</th>
          <th>Out #2</th>
          <th>Name</th>
          <th>Arguments</th>
          <th>Mode</th>
          <th>Units In</th>
          <th>Units Out</th>
          <th>Ratio</th>
          <th>Time (ms)</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>0</td>
          <td>1</td>
          <td>-</td>
          <td>SolutionInjection</td>
          <td>solutions=[{}]</td>
          <td>-</td>
          <td>0</td>
          <td>1</td>
          <td>0.00</td>
          <td>0</td>
        </tr>

        <tr>
          <td>1</td>
          <td>2</td>
          <td>-</td>
          <td>PipelineJoin</td>
          <td>pattern=distinct(?s, ?p, ?o)<br>
              joinType=join<br>
              joinProjectionVars=[?s, ?p, ?o]</td>
          <td>-</td>
          <td>1</td>
          <td>6</td>
          <td>6.00</td>
          <td>1</td>
        </tr>

        <tr>
          <td>2</td>
          <td>3</td>
          <td>-</td>
          <td>Projection</td>
          <td>vars=[?s, ?p, ?o]</td>
          <td>retain</td>
          <td>6</td>
          <td>6</td>
          <td>1.00</td>
          <td>2</td>
        </tr>

        <tr>
          <td>3</td>
          <td>-</td>
          <td>-</td>
          <td>Slice</td>
          <td>limit=1</td>
          <td>-</td>
          <td>1</td>
          <td>1</td>
          <td>1.00</td>
          <td>1</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>
```

HTML 在瀏覽器中顯示如下：

![\[SPARQL Explain HTML 輸出範例。\]](http://docs.aws.amazon.com/zh_tw/neptune/latest/userguide/images/sparql-explain-dynamic-html-output.png)


## DFE 啟用時的 SPARQL `explain` 輸出範例
<a name="sparql-explain-output-dfe"></a>

以下是 Neptune DFE 替代查詢引擎啟用時的 SPARQL `explain` 輸出範例：

```
╔════╤════════╤════════╤═══════════════════╤═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments                                                                                                                                                                                                               │ Mode     │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]                                                                                                                                                                                                          │ -        │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ HashIndexBuild    │ solutionSet=solutionSet1                                                                                                                                                                                                │ -        │ 1        │ 1         │ 1.00  │ 22        ║
║    │        │        │                   │ joinVars=[]                                                                                                                                                                                                             │          │          │           │       │           ║
║    │        │        │                   │ sourceType=pipeline                                                                                                                                                                                                     │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFENode           │ DFE Stats=                                                                                                                                                                                                                    │ -        │ 101      │ 100       │ 0.99  │ 32        ║
║    │        │        │                   │ ====> DFE execution time (measured by DFEQueryEngine)                                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ accepted [micros]=127                                                                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ ready [micros]=2                                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │ running [micros]=5627                                                                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ finished [micros]=0                                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> DFE execution time (measured in DFENode)                                                                                                                                                                           │          │          │           │       │           ║
║    │        │        │                   │ -> setupTime [ms]=1                                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │ -> executionTime [ms]=14                                                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │ -> resultReadTime [ms]=0                                                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> Static analysis statistics                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ --> 35907 micros spent in parser.                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ --> 7643 micros spent in range count estimation                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ --> 2895 micros spent in value resolution                                                                                                                                                                               │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ --> 39974925 micros spent in optimizer loop                                                                                                                                                                             │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ DFEJoinGroupNode[ children={                                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │   DFEPatternNode[(?1, TERM[117442062], ?2, ?3) . project DISTINCT[?1, ?2] {rangeCountEstimate=100},                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │     OperatorInfoWithAlternative[                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │       rec=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_PIPELINE_JOIN,                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0002,comp=0.0000,mem=0],                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0002,comp=0.0000,mem=0]]],                                                                                                             │          │          │           │       │           ║
║    │        │        │                   │       alt=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_HASH_JOIN,                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0003,comp=0.0000,mem=3212],                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=1.0000,out=100.0000,io=0.0003,comp=0.0000,mem=3212]]]]],                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │   DFEPatternNode[(?1, TERM[150997262], ?4, ?5) . project DISTINCT[?1, ?4] {rangeCountEstimate=100},                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │     OperatorInfoWithAlternative[                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │       rec=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_HASH_JOIN,                                                                                                                                                                                     │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0003,comp=0.0000,mem=6400],                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0003,comp=0.0000,mem=6400]]],                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │       alt=OperatorInfo[                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         type=INCREMENTAL_PIPELINE_JOIN,                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │         costEstimates=OperatorCostEstimates[                                                                                                                                                                            │          │          │           │       │           ║
║    │        │        │                   │           costEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0010,comp=0.0000,mem=0],                                                                                                                      │          │          │           │       │           ║
║    │        │        │                   │           worstCaseCostEstimate=OperatorCostEstimate[in=100.0000,out=100.0000,io=0.0010,comp=0.0000,mem=0]]]]]                                                                                                          │          │          │           │       │           ║
║    │        │        │                   │ },                                                                                                                                                                                                                      │          │          │           │       │           ║
║    │        │        │                   │ ]                                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> DFE configuration:                                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │ solutionChunkSize=5000                                                                                                                                                                                                  │          │          │           │       │           ║
║    │        │        │                   │ ouputQueueSize=20                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ numComputeCores=3                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ maxParallelIO=10                                                                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │ numInitialPermits=12                                                                                                                                                                                                    │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ====> DFE configuration (reported back)                                                                                                                                                                                 │          │          │           │       │           ║
║    │        │        │                   │ numComputeCores=3                                                                                                                                                                                                       │          │          │           │       │           ║
║    │        │        │                   │ maxParallelIO=2                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ numInitialPermits=12                                                                                                                                                                                                    │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ ===> Statistics & operator histogram                                                                                                                                                                                    │          │          │           │       │           ║
║    │        │        │                   │ ==> Statistics                                                                                                                                                                                                          │          │          │           │       │           ║
║    │        │        │                   │ -> 3741 / 3668 micros total elapsed (incl. wait / excl. wait)                                                                                                                                                           │          │          │           │       │           ║
║    │        │        │                   │ -> 3741 / 3 millis total elapse (incl. wait / excl. wait)                                                                                                                                                               │          │          │           │       │           ║
║    │        │        │                   │ -> 3741 / 0 secs total elapsed (incl. wait / excl. wait)                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │ ==> Operator histogram                                                                                                                                                                                                  │          │          │           │       │           ║
║    │        │        │                   │ -> 47.66% of total time (excl. wait): pipelineScan (2 instances)                                                                                                                                                        │          │          │           │       │           ║
║    │        │        │                   │ -> 10.99% of total time (excl. wait): merge (1 instances)                                                                                                                                                               │          │          │           │       │           ║
║    │        │        │                   │ -> 41.17% of total time (excl. wait): symmetricHashJoin (1 instances)                                                                                                                                                   │          │          │           │       │           ║
║    │        │        │                   │ -> 0.19% of total time (excl. wait): drain (1 instances)                                                                                                                                                                │          │          │           │       │           ║
║    │        │        │                   │                                                                                                                                                                                                                         │          │          │           │       │           ║
║    │        │        │                   │ nodeId | out0   | out1 | opName            | args                                             | rowsIn | rowsOut | chunksIn | chunksOut | elapsed* | outWait | outBlocked | ratio    | rate* [M/s] | rate [M/s] | %     │          │          │           │       │           ║
║    │        │        │                   │ ------ | ------ | ---- | ----------------- | ------------------------------------------------ | ------ | ------- | -------- | --------- | -------- | ------- | ---------- | -------- | ----------- | ---------- | ----- │          │          │           │       │           ║
║    │        │        │                   │ node_0 | node_2 | -    | pipelineScan      | (?1, TERM[117442062], ?2, ?3) DISTINCT [?1, ?2]  | 0      | 100     | 0        | 1         | 874      | 0       | 0          | Infinity | 0.1144      | 0.1144     | 23.83 │          │          │           │       │           ║
║    │        │        │                   │ node_1 | node_2 | -    | pipelineScan      | (?1, TERM[150997262], ?4, ?5) DISTINCT [?1, ?4]  | 0      | 100     | 0        | 1         | 874      | 0       | 0          | Infinity | 0.1144      | 0.1144     | 23.83 │          │          │           │       │           ║
║    │        │        │                   │ node_2 | node_4 | -    | symmetricHashJoin |                                                  | 200    | 100     | 2        | 2         | 1510     | 73      | 0          | 0.50     | 0.0662      | 0.0632     | 41.17 │          │          │           │       │           ║
║    │        │        │                   │ node_3 | -      | -    | drain             |                                                  | 100    | 0       | 1        | 0         | 7        | 0       | 0          | 0.00     | 0.0000      | 0.0000     | 0.19  │          │          │           │       │           ║
║    │        │        │                   │ node_4 | node_3 | -    | merge             |                                                  | 100    | 100     | 2        | 1         | 403      | 0       | 0          | 1.00     | 0.2481      | 0.2481     | 10.99 │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 4      │ -      │ HashIndexJoin     │ solutionSet=solutionSet1                                                                                                                                                                                                │ -        │ 100      │ 100       │ 1.00  │ 4         ║
║    │        │        │                   │ joinType=join                                                                                                                                                                                                           │          │          │           │       │           ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ Distinct          │ vars=[?s, ?o, ?o1]                                                                                                                                                                                                      │ -        │ 100      │ 100       │ 1.00  │ 9         ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ -      │ Projection        │ vars=[?s, ?o, ?o1]                                                                                                                                                                                                      │ retain   │ 100      │ 100       │ 1.00  │ 2         ║
╟────┼────────┼────────┼───────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ -      │ -      │ TermResolution    │ vars=[?s, ?o, ?o1]                                                                                                                                                                                                      │ id2value │ 100      │ 100       │ 1.00  │ 11        ║
╚════╧════════╧════════╧═══════════════════╧═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════════╧══════════╧═══════════╧═══════╧═══════════╝
```

# Neptune SPARQL `explain` 運算子
<a name="sparql-explain-operators"></a>

以下各節描述目前 Amazon Neptune 中可用的 SPARQL `explain` 功能運算子和參數。

**重要**  
SPARQL `explain` 功能仍在進行改善，這裡記載的運算子和參數在未來的版本中可能會加以變更。

**Topics**
+ [

## `Aggregation`運算子
](#sparql-explain-operator-aggregation)
+ [

## `ConditionalRouting`運算子
](#sparql-explain-operator-conditional-routing)
+ [

## `Copy`運算子
](#sparql-explain-operator-copy)
+ [

## `DFENode`運算子
](#sparql-explain-operator-dfenode)
+ [

## `Distinct`運算子
](#sparql-explain-operator-distinct)
+ [

## `Federation`運算子
](#sparql-explain-operator-federation)
+ [

## `Filter`運算子
](#sparql-explain-operator-filter)
+ [

## `HashIndexBuild`運算子
](#sparql-explain-operator-hash-index-build)
+ [

## `HashIndexJoin`運算子
](#sparql-explain-operator-hash-index-join)
+ [

## `MergeJoin`運算子
](#sparql-explain-operator-merge-join)
+ [

## `NamedSubquery`運算子
](#sparql-explain-operator-named-subquery)
+ [

## `PipelineJoin`運算子
](#sparql-explain-operator-pipeline-join)
+ [

## `PipelineCountJoin`運算子
](#sparql-explain-operator-pipeline-count-join)
+ [

## `PipelinedHashIndexJoin`運算子
](#sparql-explain-operator-pipeline-hash-index-join)
+ [

## `Projection`運算子
](#sparql-explain-operator-projection)
+ [

## `PropertyPath`運算子
](#sparql-explain-operator-property-path)
+ [

## `TermResolution`運算子
](#sparql-explain-operator-term-resolution)
+ [

## `Slice`運算子
](#sparql-explain-operator-slice)
+ [

## `SolutionInjection`運算子
](#sparql-explain-operator-solution-injection)
+ [

## `Sort`運算子
](#sparql-explain-operator-sort)
+ [

## `VariableAlignment`運算子
](#sparql-explain-operator-variable-alignment)

## `Aggregation`運算子
<a name="sparql-explain-operator-aggregation"></a>

該運算子會執行一個或多個彙總，以實作 `count`、`max`、`min`、`sum` 等 SPARQL 彙總運算子的語意。

`Aggregation` 附帶使用 `groupBy` 子句的選用分組，以及選用的 `having` 限制。

**引數**
+ `groupBy` – (*選用*) 提供的 `groupBy` 子句會根據分組的傳入解決方案來指定運算式序列。
+ `aggregates` – (*必要*) 指定彙總運算式的排序清單。
+ `having` – (*選用*) 會按照 SPARQL 查詢中 `having` 子句的指示，將限制新增至群組中的篩選條件。

## `ConditionalRouting`運算子
<a name="sparql-explain-operator-conditional-routing"></a>

該運算子會根據指定的條件路由傳入解決方案。符合該條件的解決方案會路由至 `Out #1` 所參考的運算子 ID，而不符合條件的解決方案則會路由至 `Out #2` 參考的運算子。

**引數**
+ `condition` – (*必要*) 路由條件。

## `Copy`運算子
<a name="sparql-explain-operator-copy"></a>

該運算子會依指定模式的規定來委派解決方案串流。

**模式**
+ `forward` – 將解決方案轉送至 `Out #1` 識別的下游運算子。
+ `duplicate` – 複製解決方案並將其分別轉送至 `Out #1` 和 `Out #2` 識別的兩個運算子。

`Copy` 並沒有任何引數。

## `DFENode`運算子
<a name="sparql-explain-operator-dfenode"></a>

這個運算子是 DFE 替代查詢引擎所執行之計畫的抽象。詳細的 DFE 計畫會在此運算子的引數中加以概述。引數目前已過載，以包含 DFE 計畫的詳細執行期統計資料。它包含按 DFE 查詢執行的各個步驟所花費的時間。

DFE 查詢計畫的邏輯最佳化抽象語法樹 (AST) 會與規劃時所考慮之運算子類型的相關資訊，以及要執行運算子的相關聯最佳和最差成本一起列印。AST 目前由以下類型的節點組成：
+ `DFEJoinGroupNode` – 代表一個或多個 `DFEPatternNodes` 的聯結。
+ `DFEPatternNode` – 使用從基礎資料庫中投影出來的相符元組封裝基礎模式。

子區段 `Statistics & Operator histogram` 包含有關 `DataflowOp` 計畫執行時間，以及每個運算子所使用之 CPU 時間明細的詳細資訊。這個子區段下面有一個資料表，其會列印 DFE 所執行之計畫的詳細執行期統計資料。

**注意**  
因為 DFE 是在實驗室模式下發行的一項實驗功能，所以其 `explain` 輸出的確切格式可能會有所變更。

## `Distinct`運算子
<a name="sparql-explain-operator-distinct"></a>

該運算子會運算變數子集上不同的投影，藉此消除重複項目。因此，流入的解決方案數量會大於或等於流出的解決方案數量。

**引數**
+ `vars` – (*必要*) 要套用 `Distinct` 投影的變數。

## `Federation`運算子
<a name="sparql-explain-operator-federation"></a>

將指定的查詢傳遞至指定的遠端 SPARQL 端點。

**引數**
+ `endpoint` – (*必要*) SPARQL `SERVICE` 陳述式中的端點 URL。這可以是常數字串，或者如果查詢端點是根據相同查詢中的變數來決定，則它可以是變數名稱。
+ `query` – (*必要*) 要傳送至遠端端點的重建查詢字串。即使用戶端未指定任何字首，引擎也會將預設字首新增至此查詢。
+ `silent` – (*必要*) 布林值，指出 `SILENT` 關鍵字是否出現在此關鍵字之後。`SILENT` 會告知引擎，即使遠端 `SERVICE` 部分失敗，也不要讓整個查詢失敗。

## `Filter`運算子
<a name="sparql-explain-operator-filter"></a>

該運算子會篩選傳入的解決方案。唯有符合篩選條件的解決方案可轉送至上游運算子，其他所有解決方案則會遭到捨棄。

**引數**
+ `condition` – (*必要*) 篩選條件。

## `HashIndexBuild`運算子
<a name="sparql-explain-operator-hash-index-build"></a>

該運算子會接受繫結清單並將其多工緩衝處理至雜湊索引，該雜湊索引的名稱是由 `solutionSet` 引數所定義。後續的運算子通常會對這個解決方案集執行聯結操作，再用該名稱指向解決方案集。

**引數**
+ `solutionSet` – (*必要*) 雜湊索引解決方案集的名稱。
+ `sourceType` – (*必要*) 所取得雜湊索引中存放繫結的來源類型：
  + `pipeline` – 將運算子管道中來自下游運算子的傳入解決方案多工緩衝處理至雜湊索引。
  + `binding set` – 將 `sourceBindingSet` 引數指定的固定繫結集多工緩衝處理至雜湊索引。
+ `sourceBindingSet` – (*選用*) 如果 `sourceType` 引數值為 `binding set`，則此引數會指定將靜態繫結集多工緩衝處理至雜湊索引。

## `HashIndexJoin`運算子
<a name="sparql-explain-operator-hash-index-join"></a>

該運算子會對 `solutionSet` 引數辨識的雜湊索引解決方案集執行傳入解決方案聯結操作。

**引數**
+ `solutionSet` – (*必要*) 要據以聯結的解決方案集名稱。這必須是在先前步驟中使用 `HashIndexBuild` 運算子建構的雜湊索引解決方案。
+ `joinType` – (*必要*) 要執行的聯結類型：
  + `join` – 一般聯結，所有共用變數間需要有完全相符的項目。
  + `optional` – `optional` 聯結，其會使用 SPARQL `OPTIONAL` 運算子語義。
  + `minus` – `minus` 操作會使用 SPARQL `MINUS` 運算子語義來保留沒有任何聯結夥伴的映射。
  + `existence check` – 檢查是否有聯結夥伴，並將 `existenceCheckResultVar` 變數繫結至檢查結果。
+ `constraints` – (*選用*) 進行聯結時所考量的其他聯結限制。不符合這些限制的聯結皆會予以捨棄。
+ `existenceCheckResultVar` – (*選用*) 只能用在 `joinType` 等於 `existence check` 的聯結 (請參閱先前提及的 `joinType` 引數)。

## `MergeJoin`運算子
<a name="sparql-explain-operator-merge-join"></a>

該運算子會對 `solutionSets` 辨識的多個解決方案集執行合併聯結。

**引數**
+ `solutionSets` – (*必要*) 要互相聯結的解決方案集。

## `NamedSubquery`運算子
<a name="sparql-explain-operator-named-subquery"></a>

該運算子會針對 `subQuery` 引數識別的子查詢觸發評估作業，並將結果多工緩衝處理至 `solutionSet` 引數指定的解決方案集。運算子的傳入解決方案會轉送至該子查詢，接著轉送至下一個運算子。

**引數**
+ `subQuery` – (*必要*) 要評估的子查詢名稱；輸出中會明確呈現該子查詢。
+ `solutionSet` – (*必要*) 用來儲存子查詢結果的解決方案集名稱。

## `PipelineJoin`運算子
<a name="sparql-explain-operator-pipeline-join"></a>

該運算子會接收先前運算子的輸出做為輸入，並將其聯結至 `pattern` 引數定義的元組模式。

**引數**
+ `pattern` – (*必要*) 這個模式會採用 subject-predicate-object 三元組格式，並選擇性地使用做為聯結基礎的圖形元組。如果 `distinct` 為指定的模式值，則聯結僅會從 `projectionVars` 引數指定的投影變數中擷取不同解決方案，而不是所有相符的解決方案。
+ `inlineFilters` – (*選用*) 要套用至模式中變數的一組篩選條件。系統會一併評估模式與這些篩選條件。
+ `joinType` – (*必要*) 要執行的聯結類型：
  + `join` – 一般聯結，所有共用變數間需要有完全相符的項目。
  + `optional` – `optional` 聯結，其會使用 SPARQL `OPTIONAL` 運算子語義。
  + `minus` – `minus` 操作會使用 SPARQL `MINUS` 運算子語義來保留沒有任何聯結夥伴的映射。
  + `existence check` – 檢查是否有聯結夥伴，並將 `existenceCheckResultVar` 變數繫結至檢查結果。
+ `constraints` – (*選用*) 進行聯結時所考量的其他聯結限制。不符合這些限制的聯結皆會予以捨棄。
+ `projectionVars` – (*選用*) 投影變數。此引數需與 `distinct := true` 結合使用，以在指定的一組變數內強制擷取不同投影。
+ `cutoffLimit` – (*選用*) 擷取的聯結夥伴數量截止限制。雖然沒有任何預設限制，但您可以在執行聯結操作時將此引數設為 1 以實作 `FILTER (NOT) EXISTS` 子句，其足以證明或駁斥聯結夥伴的存在。

## `PipelineCountJoin`運算子
<a name="sparql-explain-operator-pipeline-count-join"></a>

該運算子為 `PipelineJoin` 的變體；其不會執行聯結操作，而是計算相符的聯合夥伴數量，並將計數繫結至 `countVar` 引數指定的變數。

**引數**
+ `countVar` – (*必要*) 應繫結計數結果 (即聯結夥伴數量) 的變數。
+ `pattern` – (*必要*) 這個模式會採用 subject-predicate-object 三元組格式，並選擇性地使用做為聯結基礎的圖形元組。如果 `distinct` 為指定的模式值，則聯結僅會從 `projectionVars` 引數指定的投影變數中擷取不同解決方案，而不是所有相符的解決方案。
+ `inlineFilters` – (*選用*) 要套用至模式中變數的一組篩選條件。系統會一併評估模式與這些篩選條件。
+ `joinType` – (*必要*) 要執行的聯結類型：
  + `join` – 一般聯結，所有共用變數間需要有完全相符的項目。
  + `optional` – `optional` 聯結，其會使用 SPARQL `OPTIONAL` 運算子語義。
  + `minus` – `minus` 操作會使用 SPARQL `MINUS` 運算子語義來保留沒有任何聯結夥伴的映射。
  + `existence check` – 檢查是否有聯結夥伴，並將 `existenceCheckResultVar` 變數繫結至檢查結果。
+ `constraints` – (*選用*) 進行聯結時所考量的其他聯結限制。不符合這些限制的聯結皆會予以捨棄。
+ `projectionVars` – (*選用*) 投影變數。此引數需與 `distinct := true` 結合使用，以在指定的一組變數內強制擷取不同投影。
+ `cutoffLimit` – (*選用*) 擷取的聯結夥伴數量截止限制。雖然沒有任何預設限制，但您可以在執行聯結操作時將此引數設為 1 以實作 `FILTER (NOT) EXISTS` 子句，其足以證明或駁斥聯結夥伴的存在。

## `PipelinedHashIndexJoin`運算子
<a name="sparql-explain-operator-pipeline-hash-index-join"></a>

這是一體化的建置雜湊索引和聯結運算子。它會取得繫結清單、將它們多工緩衝處理至雜湊索引，然後針對雜湊索引聯結傳入的解決方案。

**引數**
+ `sourceType` – (*必要*) 所取得雜湊索引中儲存繫結的來源類型：
  + `pipeline` – 導致 `PipelinedHashIndexJoin` 將運算子管道中來自下游運算子的傳入解決方案多工緩衝處理至雜湊索引。
  + `binding set` – 導致 `PipelinedHashIndexJoin` 將 `sourceBindingSet` 引數指定的固定繫結集多工緩衝處理至雜湊索引。
+ `sourceSubQuery ` – (*選用*) 如果 `sourceType` 引數值為 `pipeline`，此引數會指定進行評估並多工緩衝處理至雜湊索引的子查詢。
+ `sourceBindingSet ` – (*選用*) 如果 `sourceType` 引數值為 `binding set`，則此引數會指定將靜態繫結集多工緩衝處理至雜湊索引。
+ `joinType` – (*必要*) 要執行的聯結類型：
  + `join` – 一般聯結，所有共用變數間需要有完全相符的項目。
  + `optional` – `optional` 聯結，其會使用 SPARQL `OPTIONAL` 運算子語義。
  + `minus` – `minus` 操作會使用 SPARQL `MINUS` 運算子語義來保留沒有任何聯結夥伴的映射。
  + `existence check` – 檢查是否有聯結夥伴，並將 `existenceCheckResultVar` 變數繫結至檢查結果。
+ `existenceCheckResultVar` – (*選用*) 只會用於 `joinType` 等於 `existence check` 的聯結 (請參閱上述的 joinType 引數)。

## `Projection`運算子
<a name="sparql-explain-operator-projection"></a>

該運算子會在變數子集上進行投影。流入的解決方案數量會等同於流出的解決方案數量，但解決方案的圖形會因模式設定而異。

**模式**
+ `retain` – 僅在解決方案中保留由 `vars` 引數指定的變數。
+ `drop` – 捨棄由 `vars` 引數指定的所有變數。

**引數**
+ `vars` – (*必要*) 要保留或捨棄的變數，取決於模式設定。

## `PropertyPath`運算子
<a name="sparql-explain-operator-property-path"></a>

啟用遞迴屬性路徑，例如 `+` 或 `*`。Neptune 根據 `iterationTemplate` 引數指定的範本實作固定點迭代方法。系統會針對每個固定點反覆運算項目將已知的左側或右側變數繫結至範本，直到找不到任何新的解決方案為止。

**引數**
+ `iterationTemplate` – (*必要*) 用來實作固定點迭代的子查詢範本名稱。
+ `leftTerm` – (*必要*) 位於屬性路徑左側的字詞 (變數或常值)。
+ `rightTerm` – (*必要*) 位於屬性路徑右側的字詞 (變數或常值)。
+ `lowerBound` – (*必要*) 固定點迭代的下限 (適用於 `*` 查詢的 `0`，或適用於 `+` 查詢的 `1`)。

## `TermResolution`運算子
<a name="sparql-explain-operator-term-resolution"></a>

該運算子會將內部字串識別符值轉換為各自對應的外部字串，或將外部字串轉換為內部字串識別符值，視模式而定。

**模式**
+ `value2id` – 將常值和 URI 等字詞映射至對應的內部 ID 值 (內部值編碼)。
+ `id2value` – 將內部 ID 值映射至對應的常值和 URI 等字詞 (內部值解碼)。

**引數**
+ `vars` – (*必要*) 指定字串或內部字串 ID 需進行映射的變數。

## `Slice`運算子
<a name="sparql-explain-operator-slice"></a>

該運算子會使用 SPARQL `LIMIT` 和 `OFFSET` 子句的語意，在傳入解決方案串流上實作配量。

**引數**
+ `limit` – (*選用*) 對要轉送之解決方案的限制。
+ `offset` – (*選用*) 評估解決方案以進行轉送的偏移量。

## `SolutionInjection`運算子
<a name="sparql-explain-operator-solution-injection"></a>

該運算子不會接收任何輸入，其會將靜態解決方案插入查詢計劃，並在 `solutions` 引數中加以記錄。

查詢計劃一律會從插入的靜態項目開始執行。如果可以結合各種來源的靜態繫結，進而從查詢本身衍生取得 (例如從 `VALUES` 或 `BIND` 子句) 要插入的靜態解決方案，則 `SolutionInjection` 運算子就會插入這些衍生的靜態解決方案。在最簡單的情況下，這會反映出外部 `VALUES` 子句所指示的繫結。

如果不能自查詢衍生取得任何靜態解決方案，`SolutionInjection` 就會插入空白的解決方案，也就是所謂的通用解決方案。在整個查詢評估過程中，系統會擴展並倍增這個解決方案。

**引數**
+ `solutions` – (*必要*) 運算子插入的解決方案序列。

## `Sort`運算子
<a name="sparql-explain-operator-sort"></a>

該運算子會使用指定排序條件來排列解決方案集。

**引數**
+ `sortOrder` – (*必要*) 變數的排序清單，各包含 `ASC` (遞增) 或 `DESC` (遞減) 識別符，其會按照順序來排列解決方案集。

## `VariableAlignment`運算子
<a name="sparql-explain-operator-variable-alignment"></a>

該運算子會逐一檢查所有解決方案，並針對其中的兩個變數執行校準作業。此處的變數指的是指定的 `sourceVar` 值和指定的 `targetVar` 值。

如果解決方案中的 `sourceVar` 和 `targetVar` 值相同，系統就會將該變數視為已經過校準並轉送解決方案，然後投射出多餘的 `sourceVar`。

若變數繫結至不同值，解決方案就會完全遭到排除。

**引數**
+ `sourceVar` – (*必要*) 要與目標變數相比的來源變數。若在解決方案中成功完成校準，表示兩個變數擁有相同值，且系統會投射出來源變數。
+ `targetVar` – (*必要*) 與來源變數相比的目標變數。即使校準成功，該值仍會保留不變。

# Neptune 中 SPARQL `explain` 的限制
<a name="sparql-explain-limitations"></a>

Neptune SPARQL `explain` 功能版本具有下列限制。

**Neptune 目前僅在 SPARQL SELECT 查詢中支援 Explain**  
如需其他查詢形式評估程序的相關資訊，例如 `ASK`、`CONSTRUCT`、`DESCRIBE` 和 `SPARQL UPDATE` 查詢，您可以將這些查詢轉換為 SELECT 查詢。然後，改用 `explain` 來檢查對應的 SELECT 查詢。

例如，若要取得與 `ASK WHERE {...}` 查詢相關的 `explain` 資訊，使用 `explain` 執行對應的 `SELECT WHERE {...} LIMIT 1`。

同樣地，對於 `CONSTRUCT {...} WHERE {...}` 查詢，請捨棄 `CONSTRUCT {...}` 部分並使用 `explain`，在第二個 `WHERE {...}` 子句執行 `SELECT` 查詢。對第二個 `WHERE` 子句進行評估通常也揭露處理 `CONSTRUCT` 查詢的主要挑戰，因為從第二個 `WHERE` 傳到 `CONSTRUCT` 範本的解決方案通常只需要直接替換。

**解釋運算子在未來版本可能變更**  
SPARQL `explain` 運算子及其參數可能在未來版本變更。

**解釋輸出在未來版本可能變更**  
例如，欄標題可能會變更，且可能會將更多欄新增到資料表。

# Neptune 中使用 `SERVICE` 延伸模組的 SPARQL 聯合查詢
<a name="sparql-service"></a>

Amazon Neptune 完整支援使用 `SERVICE` 關鍵字的 SPARQL 聯合查詢延伸模組。(如需詳細資訊，請參閱 [SPARQL 1.1 聯合查詢](https://www.w3.org/TR/sparql11-federated-query/)。)

`SERVICE` 關鍵字會指示 SPARQL 查詢引擎對遠端 SPARQL 端點執行部分查詢，並撰寫最終查詢結果。只有 `READ` 操作是可行的。不支援 `WRITE` 和 `DELETE` 操作。Neptune 只能針對可在其虛擬私有雲端 (VPC) 內存取的 SPARQL 端點執行聯合查詢。不過，您也可以在 VPC 中使用反向代理，使外部資料來源可在 VPC 內存取。

**注意**  
當 SPARQL `SERVICE` 用來將一個查詢聯合到相同 VPC 中兩個以上的 Neptune 叢集時，安全群組必須設定為允許所有這些 Neptune 叢集彼此通話。

**重要**  
SPARQL 1.1 聯合會在將查詢和參數傳遞至外部 SPARQL 端點時，代您提出服務請求。您有責任驗證外部 SPARQL 端點是否滿足您應用程式的資料處理和安全需求。

## Neptune 聯合查詢的範例
<a name="sparql-service-example-1"></a>

以下簡單範例說明 SPARQL 聯合查詢的運作方式。

假設客戶將以下查詢傳送至 *Neptune-1*，網址為 `http://neptune-1:8182/sparql`。

```
SELECT * WHERE {
   ?person rdf:type foaf:Person .
   SERVICE <http://neptune-2:8182/sparql> {
       ?person foaf:knows ?friend .
    }
}
```

1. *Neptune-1* 評估第一個查詢模式 (*Q-1*)，即 `?person rdf:type foaf:Person`，會使用結果來解析 *Q-2* (`?person foaf:knows ?friend`) 中的 `?person`，並將產生的模式轉送至 *Neptune-2*，網址為 `http://neptune-2:8182/sparql`。

1. *Neptune-2* 評估 *Q-2*，並將結果傳回至 *Neptune-1*。

1. *Neptune-1* 聯結這兩種模式的解決方案，並將結果傳回給客戶。

下圖顯示此流程。

![\[流程圖顯示正要評估的 SPARQL 聯合查詢模式，以及傳回給用戶端的回應。\]](http://docs.aws.amazon.com/zh_tw/neptune/latest/userguide/images/federated.png)


**注意**  
根據預設，最佳化工具會確定 `SERVICE` 指令在查詢執行中的哪個點執行。您可以使用 [joinOrder](sparql-query-hints-joinOrder.md) 查詢提示覆寫此置放。

## Neptune 中聯合查詢的存取控制
<a name="sparql-service-auth"></a>

Neptune 使用 AWS Identity and Access Management (IAM) 進行身分驗證和授權。聯合查詢的存取控制可涉及多個 Neptune 資料庫執行個體。這些執行個體可能會有不同的存取控制需求。在某些情況下，這會限制您進行聯合查詢的能力。

考慮上一節中展示的簡單範例。*Neptune-1* 會透過呼叫其所用的同一憑證呼叫 *Neptune-2*。
+ 如果 *Neptune-1* 需要 IAM 身分驗證和授權，但 *Neptune-2* 不需要，則您只需要 *Neptune-1* 的適當 IAM 許可，即可進行聯合查詢。
+ 如果 *Neptune-1* 和 *Neptune-2* 都需要 IAM 身分驗證和授權，您需要連線兩個資料庫的 IAM 許可才能進行聯合查詢。兩個叢集也必須位於相同 AWS 帳戶和相同區域。目前不支援跨區域和/或跨帳戶聯合查詢架構。
+ 不過，在 *Neptune-1* 未啟用 IAM，但 *Neptune-2* 卻啟用它的情況下，您無法進行聯合查詢。原因是 *Neptune-1* 無法擷取您的 IAM 憑證，並將其傳遞至 *Neptune-2*，以授權查詢的第二個部分。