

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# SPARQL을 사용하여 Neptune 그래프에 액세스
<a name="access-graph-sparql"></a>

SPARQL은 웹용으로 설계된 그래프 데이터 형식인 리소스 기술 프레임워크(RDF)의 쿼리 언어입니다. Amazon Neptune은 SPARQL 1.1과 호환됩니다. 따라서 Neptune DB 인스턴스에 연결하고 [SPARQL 1.1 쿼리 언어](https://www.w3.org/TR/sparql11-query/) 사양에서 설명하는 쿼리 언어를 사용하여 그래프를 쿼리할 수 있습니다.

 SPARQL의 쿼리는 반환하는 변수를 지정하는 `SELECT` 절과 그래프에서 일치시킬 데이터를 지정하는 `WHERE` 절로 구성됩니다. SPARQL 쿼리에 익숙하지 않은 경우 [SPARQL 1.1 쿼리 언어](https://www.w3.org/TR/sparql11-query/)의 [단순 쿼리 작성](https://www.w3.org/TR/sparql11-query/#WritingSimpleQueries)을 참조하세요.

**중요**  
데이터를 로드할 때 `SPARQL UPDATE INSERT`로 소량 데이터 세트 작업이 가능하지만 파일에서 상당량의 데이터를 로드해야 할 경우에는 [Amazon Neptune 대량 로더를 사용하여 데이터 수집](bulk-load.md)를 참조하십시오.

Neptune의 SPARQL 구현 세부 사항에 대한 자세한 내용은 [SPARQL 표준 규정 준수](feature-sparql-compliance.md) 섹션을 참조하세요.

시작하기 전에 다음을 완비해야 합니다.
+ Neptune DB 인스턴스. Neptune DB 인스턴스 생성에 대한 자세한 내용은 [Amazon Neptune 클러스터 생성](get-started-create-cluster.md) 섹션을 참조하세요.
+ 사용자의 Neptune DB 인스턴스와 동일한 Virtual Private Cloud(VPC)에 있는 Amazon EC2 인스턴스입니다.

**Topics**
+ [RDF4J 콘솔을 사용하여 Neptune DB 인스턴스에 연결](access-graph-sparql-rdf4j-console.md)
+ [RDF4J 워크벤치를 사용하여 Neptune DB 인스턴스에 연결](access-graph-sparql-rdf4j-workbench.md)
+ [Java를 사용하여 Neptune DB 인스턴스에 연결](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)
+ [`SERVICE` 확장을 사용하는 Neptune의 SPARQL 페더레이션된 쿼리](sparql-service.md)

# RDF4J 콘솔을 사용하여 Neptune DB 인스턴스에 연결
<a name="access-graph-sparql-rdf4j-console"></a>



RDF4J 콘솔을 사용하여 REPL(read-eval-print loop) 환경에서 리소스 기술 프레임워크(RDF) 그래프 및 쿼리를 실험할 수 있습니다.

원격 그래프 데이터베이스를 리포지토리로 추가하고 RDF4J 콘솔에서 쿼리할 수 있습니다. 이 섹션에서는 RDF4J 콘솔을 구성하여 원격으로 Neptune DB 인스턴스에 연결하는 방법을 살펴봅니다.

**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 DB 인스턴스용 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/ko_kr/neptune/latest/userguide/access-graph-sparql-rdf4j-console.html)

   사용자의 Neptune DB 인스턴스 주소를 찾는 방법은 [Amazon Neptune 엔드포인트에 연결](feature-overview-endpoints.md) 섹션을 참조하세요.

   작업에 성공하면 다음 메시지가 표시됩니다.

    

   ```
   Repository created
   ```

1. `>` 프롬프트에 다음을 입력하여 Neptune DB 인스턴스에 연결합니다.

   ```
   open neptune
   ```

   작업에 성공하면 다음 메시지가 표시됩니다.

    

   ```
   Opened repository 'neptune'
   ```

   이제 `neptune>` 프롬프트가 표시됩니다. 이 프롬프트에서 Neptune 그래프를 기준으로 쿼리를 실행할 수 있습니다.

    
**참고**  
리포지토리가 추가되었으므로, 다음에 `bin/console.sh`를 실행할 때 `open neptune` 명령을 즉시 실행하여 Neptune DB 인스턴스에 연결할 수 있습니다.

1. `neptune>` 프롬프트에 다음을 입력하고 10개 제한이 있는 `?s ?p ?o` 쿼리를 사용하여 그래프에서 최대 10개의 트리플(subject-predicate-object)을 반환하는 SPARQL 쿼리를 실행합니다. 다른 것을 쿼리하려면 `sparql` 명령 뒤의 텍스트를 다른 SPARQL 쿼리로 바꿉니다.

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

# RDF4J 워크벤치를 사용하여 Neptune DB 인스턴스에 연결
<a name="access-graph-sparql-rdf4j-workbench"></a>

이 섹션에서는 RDF4J 워크벤치와 RDF4J 서버를 사용하여 Amazon Neptune DB 인스턴스에 연결하는 방법을 설명합니다. RDF4J 서버가 필요한 이유는 Neptune SPARQL HTTP REST 엔드포인트와 RDF4J 워크벤치 사이에서 프록시 역할을 하기 때문입니다.

RDF4J 워크벤치는 로컬 파일 로드를 포함해 그래프를 간단하게 실험할 수 있는 인터페이스를 제공합니다. 자세한 내용은 RDF4J 설명서의 [섹션 추가](https://rdf4j.org/documentation/tools/server-workbench/#add)를 참조하십시오.

**사전 조건**  
시작하기 전에 다음을 수행하십시오.
+ Java 1.8 이상을 설치합니다.
+ RDF4J 서버와 RDF4J 워크벤치를 설치합니다. 자세한 내용은 [RDF4J 서버 및 RDF4J 워크벤치 설치](https://rdf4j.org/documentation/tools/server-workbench/#installing-rdf4j-server-and-rdf4j-workbench)를 참조하십시오.

**RDF4J 워크벤치를 사용하여 Neptune에 연결하려면**

1. 웹 브라우저에서 RDF4J 워크벤치 웹 앱이 배포되는 URL로 이동합니다. 예를 들어, Apache Tomcat을 사용한다면 URL은 [https://*ec2\$1hostname*:8080/rdf4j-workbench/](http://localhost:8080/rdf4j-workbench/)입니다.

1. **Connect to RDF4J Server(RDF4J 서버에 연결)**가 나타나면 **RDF4J Server**가 설치되고 실행되어 서버 URL이 정확한지 확인하십시오. 그 다음에 다음 단계를 진행하십시오.

1. 왼쪽 창에서 **New repository(새 리포지토리)**를 선택합니다.

   **New repository(새 리포지토리)**에서
   + **Type(유형)** 드롭다운 목록에서 **SPARQL endpoint proxy(SPARQL 엔드포인트 프록시)**를 선택합니다.
   + **ID**에는 **neptune**을 입력합니다.
   + **제목**에는 **Neptune DB 인스턴스**를 입력합니다.

   **다음**을 선택합니다.

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 DB 인스턴스 주소를 찾는 방법은 [Amazon Neptune 엔드포인트에 연결](feature-overview-endpoints.md) 섹션을 참조하세요.

   **생성(Create)**을 선택합니다.

1. 그러면 **neptune** 리포지토리가 리포지토리 목록에 표시됩니다. 새 리포지토리를 사용하려면 몇 분 걸릴 수 있습니다.

1. 테이블의 **Id** 열에서 **neptune** 링크를 선택합니다.

1. 왼쪽 창에서 **Query(쿼리)**를 선택합니다.

    
**참고**  
**Explore(탐색)**의 메뉴 항목이 비활성화되어 있으면 RDF4J 서버에 다시 연결하고 **neptune** 리포지토리를 다시 선택해야 합니다.  
오른쪽 상단 모서리에서 **[change]** 링크를 사용하면 됩니다.

1. 쿼리 필드에서 다음 SPARQL 쿼리를 입력한 후 **Execute(실행)**을 선택합니다.

    

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

    

앞의 예제에서는 10개 제한이 있는 `?s ?p ?o` 쿼리를 사용하여 그래프에서 최대 10개의 트리플(subject-predicate-object)을 반환했습니다.

# Java를 사용하여 Neptune DB 인스턴스에 연결
<a name="access-graph-sparql-java"></a>

이 섹션에서는 Amazon Neptune DB 인스턴스에 연결하고 SPARQL 쿼리를 수행하는 완전한 Java 샘플을 실행하는 절차를 안내합니다.

사용자의 Neptune DB 인스턴스와 동일한 Virtual Private Cloud(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에 대해서만 테스트되었습니다. 다음을 입력하여 사용자의 EC2 인스턴스에 Java 8을 설치합니다.

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

1. 다음을 입력하여 사용자의 EC2 인스턴스에 Java 8을 기본 실행 시간으로 설정합니다.

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

   메시지가 표시되면 Java 8에 대한 숫자를 입력합니다.

1. 다음을 입력하여 사용자의 EC2 인스턴스에 Java 8을 기본 컴파일러로 설정합니다.

   ```
   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 DB 인스턴스의 주소로 바꿉니다.
**참고**  
사용자의 Neptune DB 인스턴스 호스트 이름을 찾는 방법은 [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
   ```

앞의 예제에서는 10개 제한이 있는 `?s ?p ?o` 쿼리를 사용하여 그래프에서 최대 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 Protocol](https://www.w3.org/TR/sparql11-protocol/#protocol) 및 [SPARQL 1.1 Query Language](https://www.w3.org/TR/sparql11-query/) 사양을 참조하십시오.

다음 주제에서는 SPARQL RDF 직렬화 형식 및 SPARQL HTTP API를 Neptune에서 사용하는 방법에 대한 정보를 제공합니다.

**Contents**
+ [HTTP REST 엔드포인트를 사용하여 Neptune DB 인스턴스에 연결](access-graph-sparql-http-rest.md)
+ [멀티파트 SPARQL 응답을 위한 선택적 HTTP 후행 헤더](access-graph-sparql-http-trailing-headers.md)
+ [Neptune에서 SPARQL이 사용하는 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 DB 인스턴스에 연결
<a name="access-graph-sparql-http-rest"></a>

**참고**  
Neptune은 현재 REST API 요청에 대해 HTTP/2를 지원하지 않습니다. 클라이언트는 엔드포인트에 연결할 때 HTTP/1.1을 사용해야 합니다.

다음은 **curl** 명령을 사용하여 SPARQL 엔드포인트에 연결하고, HTTPS를 통해 연결하고, HTTP 구문을 사용하는 방법입니다. 사용자의 Neptune DB 인스턴스와 동일한 Virtual Private Cloud(VPC)에 있는 Amazon EC2 인스턴스에서 이러한 지침을 따라야 합니다.

Neptune DB 인스턴스의 SPARQL 쿼리용 HTTP 엔드포인트는 `https://your-neptune-endpoint:port/sparql`입니다.

**참고**  
사용자의 Neptune DB 인스턴스 호스트 이름을 찾는 방법은 [Amazon Neptune 엔드포인트에 연결](feature-overview-endpoints.md) 섹션을 참조하세요.

Amazon Neptune에서는 SPARQL 쿼리용 HTTP 엔드포인트를 제공합니다. REST 인터페이스는 SPARQL 버전 1.1과 호환됩니다.

**HTTP POST를 사용하는 쿼리**  
다음 예제에서는 **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
```

앞의 예제에서는 10개 제한이 있는 `?s ?p ?o` 쿼리를 사용하여 그래프에서 최대 10개의 트리플(subject-predicate-object)을 반환했습니다. 다른 것을 쿼리하려면 다른 SPARQL 쿼리로 바꿉니다.

**참고**  
`SELECT` 및 `ASK` 쿼리에 대한 응답의 기본 MIME 미디어 유형은 `application/sparql-results+json`입니다.  
응답의 기본 MIME 유형이 `CONSTRUCT` 및 `DESCRIBE` 쿼리는 `application/n-quads`입니다.  
Neptune에서 직렬화에 대해 사용하는 미디어 유형 목록은 [Neptune SPARQL이 사용하는 RDF 직렬화 형식](sparql-media-type-support.md#sparql-serialization-formats) 섹션을 참조하세요.

**HTTP POST를 사용하는 업데이트**  
다음 예제에서는 **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 응답은 종종 2개 이상의 부분 또는 청크로 반환됩니다. 쿼리 또는 업데이트가 이러한 청크를 보내기 시작한 후 발생하는 오류를 진단하기 어려울 수 있습니다. 첫 번째 청크가 `200` HTTP 상태 코드로 도착하기 때문에 더욱 그렇습니다.

후행 헤더를 명시적으로 요청하지 않으면 Neptune은 보통 손상된 메시지 본문에 오류 메시지를 추가하는 방식으로만 오류를 보고합니다.

이러한 종류의 문제를 더 쉽게 감지하고 진단할 수 있도록 요청에 전송 인코딩(TE) 후행 헤더(`te: trailers`)를 포함할 수 있습니다(예: [TE 요청 헤더에 대한 MDN 페이지](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE) 참조). 이렇게 하면 Neptune이 응답 청크의 후행 헤더에 2개의 새 헤더 필드를 포함하게 됩니다.
+ `X-Neptune-Status`   –   응답 코드와 짧은 이름이 차례로 들어 있습니다. 예를 들어, 성공하면 후행 헤더는 `X-Neptune-Status: 200 OK`와 같습니다. 장애가 발생한 경우 응답 코드는 `X-Neptune-Status: 500 TimeLimitExceededException`과 같은 [Neptune 엔진 오류 코드](errors-engine-codes.md)가 됩니다.
+ `X-Neptune-Detail`   –   요청이 성공하면 비어 있습니다. 오류가 발생한 경우 JSON 오류 메시지가 포함됩니다. HTTP 헤더 값에는 ASCII 문자만 사용할 수 있으므로, JSON 문자열은 URL로 인코딩됩니다. 오류 메시지는 계속해서 응답 메시지 본문에 추가됩니다.

# Neptune에서 SPARQL이 사용하는 RDF 미디어 유형
<a name="sparql-media-type-support"></a>

RDF(리소스 기술 프레임워크) 데이터는 여러 방식으로 직렬화할 수 있으며, 대부분 SPARQL에서 사용하거나 출력할 수 있습니다.

## Neptune SPARQL이 사용하는 RDF 직렬화 형식
<a name="sparql-serialization-formats"></a>
+ **RDF/XML**  –   [RDF 1.1 XML Syntax](https://www.w3.org/TR/rdf-syntax-grammar/)에 정의된 RDF의 XML 직렬화입니다. 미디어 유형: `application/rdf+xml`. 일반 파일 확장명: `.rdf`
+ **N-Triples**  –   [RDF 1.1 N-Triples](https://www.w3.org/TR/n-triples/)에 정의된 RDF 그래프 인코딩을 위한 라인 기반 일반 텍스트 형식입니다. 미디어 유형: `application/n-triples`, `text/turtle` 또는 `text/plain`. 일반 파일 확장명: `.nt`
+ **N-Quads**  –   [RDF 1.1 N-Quads](https://www.w3.org/TR/n-quads/)에 정의된 RDF 그래프 인코딩을 위한 라인 기반 일반 텍스트 형식입니다. N-Triples의 확장명입니다. 미디어 유형: 7비트 US-ASCII로 인코딩될 때 `application/n-quads` 또는 `text/x-nquads`. 일반 파일 확장명: `.nq`
+ **Turtle**  –   RDF 그래프를 공통 사용 패턴 및 데이터 유형에 대한 약어를 사용하여 간단한 자연 텍스트 형식으로 완전하게 작성할 수 있는[ RDF 1.1 Turtle](https://www.w3.org/TR/turtle/)에 정의된 RDF에 대한 텍스트 구문입니다. Turtle은 N-Triples 형식은 물론 SPARQL의 트리플 패턴 구문과의 호환성 레벨을 제공합니다. 미디어 유형: `text/turtle`일반 파일 확장명: `.ttl`
+ **TriG**  –   RDF 그래프를 공통 사용 패턴 및 데이터 유형에 대한 약어를 사용하여 간단한 자연 텍스트 형식으로 완전하게 작성할 수 있는[ RDF 1.1 TriG](https://www.w3.org/TR/trig/)에 정의된 RDF에 대한 텍스트 구문입니다. TriG는 Turtle 형식의 확장명입니다. 미디어 유형: `application/trig`. 일반 파일 확장명: `.trig`
+ **N3(Notation3)**  –   [Notation3 (N3): A readable RDF syntax](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**  –   [TriX: RDF Triples in XML](https://www.hpl.hp.com/techreports/2004/HPL-2004-56.html)에 정의된 XML의 RDF 직렬화입니다. 미디어 유형: `application/trix`. 일반 파일 확장명: `.trix`
+ **SPARQL JSON Results**  –   [SPARQL 1.1 Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json)을 사용하는 RDF의 직렬화입니다. 미디어 유형: `application/sparql-results+json`. 일반 파일 확장명: `.srj`
+ **RDF4J Binary Format**  –   [RDF4J Binary RDF Format](https://rdf4j.org/documentation/reference/rdf4j-binary)에서 문서화된 RDF 데이터 인코딩을 위한 이진 형식입니다. 미디어 유형: `application/x-binary-rdf`.

## Neptune SPARQL에서 사용되는 SPARQL 결과 직렬화 형식
<a name="sparql-serialization-formats-neptune-output"></a>
+ **SPARQL XML Results**  –   [SPARQL Query Results XML Format (Second Edition)](https://www.w3.org/TR/rdf-sparql-XMLres/)에 정의된 SPARQL 쿼리 언어에서 제공하는 변수 바인딩 및 부울 결과 형식에 대한 XML 형식입니다. 미디어 유형: `application/sparql-results+xml`. 일반 파일 확장명: `.srx`
+ **SPARQL CSV and TSV Results**  –   쉼표로 구분된 값과 탭으로 구분된 값을 사용하여 `SELECT` 쿼리의 SPARQL 쿼리 결과를 표현하는 것으로, [SPARQL 1.1 Query Results CSV and TSV Formats](https://www.w3.org/TR/sparql11-results-csv-tsv/)에 정의되어 있습니다. 미디어 유형: 쉼표로 구분된 값의 경우 `text/csv`, 탭으로 구분된 값의 경우 `text/tab-separated-values`. 일반 파일 확장: 쉼표로 구분된 값의 경우 `.csv`, 탭으로 구분된 값의 경우 `.tsv`
+ **Binary Results Table**  –   SPARQL 쿼리 출력 인코딩을 위한 이진 형식입니다. 미디어 유형: `application/x-binary-rdf-results-table`.
+ **SPARQL JSON Results**  –   [SPARQL 1.1 Query Results JSON Format](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 Results](https://www.w3.org/TR/sparql11-results-json)(기본값)
+ [SPARQL XML Results](https://www.w3.org/TR/rdf-sparql-XMLres/)
+ **Binary Results Table**(미디어 유형: `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 Results](https://www.w3.org/TR/sparql11-results-json)(기본값)
+ [SPARQL XML Results](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 Results](https://www.w3.org/TR/sparql11-results-json)
+ [RDF4J Binary RDF Format](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 Results](https://www.w3.org/TR/sparql11-results-json)
+ [RDF4J Binary RDF Format](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>
  ```

**참고**  
많은 데이터를 로드해야 하는 경우 UPDATE LOAD 대신 Neptune 대량 로더를 사용하는 것이 좋습니다. 대량 로더에 대한 자세한 내용은 [Amazon Neptune 대량 로더를 사용하여 데이터 수집](bulk-load.md) 섹션을 참조하세요.

`SPARQL UPDATE LOAD`를 사용하여 Amazon S3에서 직접 데이터를 로드하거나 자체 호스팅한 웹 서버에서 가져온 파일에서 데이터를 로드할 수 있습니다. 로드할 리소스는 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 UPDATE LOAD를 사용할 때 Amazon S3에 IAM 역할을 전달할 수 없으므로, 문제의 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)
```

그러면 생성된 사전 서명된 URL을 `LOAD` 명령에 사용할 수 있습니다.

```
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)을 사용하여 액세스하는 버킷에 대해서만 작동합니다.

 아래와 같이 프라이빗 Amazon S3 버킷에서 로드하도록 웹 프록시 서버를 설정할 수도 있습니다.

**웹 서버에서 SPARQL UPDATE LOAD를 사용하여 파일을 Neptune에 로드**

1. Neptune 및 로드할 파일을 호스팅하는 VPC 내에서 실행하는 시스템에 웹 서버를 설치합니다. 예를 들어 Amazon Linux를 사용하는 경우 다음과 같이 Apache를 설치할 수 있습니다.

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

1. 로드할 RDF 파일 콘텐츠의 MIME 유형을 정의합니다. SPARQL은 웹 서버에서 보낸 `Content-type` 헤더를 사용하여 콘텐츠의 입력 형식을 결정하므로 웹 서버에 적합한 MIME 유형을 정의해야 합니다.

   예를 들어 다음 파일 확장명을 사용하여 파일 형식을 식별한다고 가정하겠습니다.
   + NTriples에 대해 `.nt`
   + NQuads에 대해 `.nq`
   + Trig에 대해 `.trig`
   + RDF/XML에 대해 `.rdf`
   + Turtle에 대해 `.ttl`
   + N3에 대해 `.n3`
   + JSON-LD에 대해 `.jsonld`

   Apache 2를 웹 서버로 사용하는 경우 `/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 유형의 매핑이 작동하는지 확인합니다. 웹 서버가 작동하고 실행 중이며 RDF 파일을 선택한 형식으로 호스팅하면 로컬 호스트에서 웹 서버로 요청을 보내 구성을 테스트할 수 있습니다.

   예를 들어 다음과 같이 요청을 보낼 수 있습니다.

   ```
   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`를 사용하면 로드 중인 소스 파일이 클 때 웹 서버에서 시간 초과를 트리거할 수 있습니다. Neptune은 스트리밍되는 파일 데이터를 처리하고 서버에 구성된 제한 시간보다 오래 걸릴 수 있는 큰 파일을 처리합니다. 이로 인해 서버가 연결을 종료하여 Neptune의 스트림에서 예기치 않은 EOF가 발생하면 다음과 같은 오류 메시지가 나타날 수 있습니다.  

```
{
  "detailedMessage":"Invalid syntax in the specified file",
  "code":"InvalidParameterException"
}
```
이 메시지가 나타나는데 소스 파일에 잘못된 구문이 포함되어 있지 않은 경우 웹 서버의 시간 초과 설정을 늘려 보십시오. 서버에서 디버그 로그를 활성화하고 시간 초과를 찾아 문제를 진단할 수도 있습니다.

# 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` 작업에 의해 DB 클러스터에서 제거됩니다.

  데이터를 언로드하려면 모든 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>
  ```

`LOAD`가 `INSERT DATA { (inline data) }`에 해당하듯이, `UNLOAD`는 `DELETE DATA { (inline data) }`에 해당합니다. `DELETE DATA`과 같이 `UNLOAD`는 빈 노드를 포함한 데이터에는 사용할 수 없습니다.

로컬 웹 서버가 다음 2개의 트리플이 포함된 `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 Bad Request.

  *메시지*: ` Blank nodes are not allowed for UNLOAD`

   
+ **`InvalidParameterException`**   –   데이터 구문이 깨졌습니다. *HTTP 상태*: 400 Bad Request.

  *메시지*: `Invalid syntax in the specified file.`

   
+ **`UnloadUrlAccessDeniedException `**   –   액세스가 거부되었습니다. *HTTP 상태*: 400 Bad Request.

  *메시지*: `Update failure: Endpoint (Neptune endpoint) reported access denied error. Please verify access.`

   
+ **`BadRequestException `**   –   원격 데이터를 검색할 수 없습니다. *HTTP 상태*: 400 Bad Request.

  *메시지*: *(HTTP 응답에 따라 다름)*

# SPARQL 쿼리 힌트
<a name="sparql-query-hints"></a>

쿼리 힌트를 사용하여 Amazon Neptune에서 특정 SPARQL 쿼리에 대한 최적화 및 평가 전략을 지정할 수 있습니다.

쿼리 힌트는 SPARQL 쿼리에 다음과 같은 부분으로 포함된 추가 트리플 패턴을 사용하여 표현됩니다.

```
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 | 지원되는 힌트 | 설명 | 
| --- | --- | --- | 
| 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은 쿼리 평가 중에 나타나는 인스턴스 데이터 관련 특성(예: 그래프의 히팅 파워 노드 등)을 간과할 수 있습니다.

데이터의 정확한 특성을 알고 있고 쿼리 실행 순서를 수동으로 지정하려는 경우 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`이라는 한 사람이 `Jane`을 포함하여 `:likes` 1,000명을 포함합니다.
+ `Jane`이라는 한 사람이 `John`을 포함하여 `:likes` 10명을 포함합니다.

**쿼리 힌트 없음**  
다음 SPARQL 쿼리는 소셜 네트워킹 데이터 세트에서 서로를 좋아하는 `John` 및 `Jane`라고 명명된 모든 쌍의 사람들을 추출합니다.

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

Neptune 쿼리 엔진은 서술문과 다른 순서로 문을 평가할 수 있습니다. 예를 들어 다음 순서로 평가할 수도 있습니다.

1. `John`라는 모든 사람을 검색합니다.

1. `:likes` 엣지 기준으로 `John`에 연결된 모든 사람을 검색합니다.

1. 이 집합을 `Jane`이라는 사람들로 필터링합니다.

1. 이 집합을 `:likes` 엣지 기준으로 `John`에 연결된 사람으로 필터링합니다.

데이터 세트에 따라 이 순서로 평가하면 1,000개의 개체가 두 번째 단계에서 추출됩니다. 세 번째 단계는 이를 단일 노드 `Jane`로 좁힙니다. 마지막 단계는 `Jane` 또한 `:likes` `John` 노드를 결정합니다.

**쿼리 힌트**  
그녀는 단 10개의 발신 `:likes` 엣지만 있기 때문에 `Jane` 노드로 시작하는 것이 유리할 것입니다. 이렇게 하면 두 번째 단계에서 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` 쿼리 힌트 및 관련 최적화를 사용하거나 사용하지 않고 작성된 쿼리를 보여줍니다.

이 예제의 경우 데이터 세트에 다음 특성이 포함되어 있다고 가정합니다.
+ `:connectedTo`이라는 레이블로 지정된 1,000개의 엣지를 포함합니다.
+ 각 `component` 노드는 평균 100개의 다른 `component` 노드에 연결됩니다.
+ 노드 사이의 4홉 주기의 연결 수는 약100입니다.

전형적인 예로 `evaluationStrategy` 힌트는 사이클을 포함하는 쿼리 패턴을 최적화하는 데 도움이 될 수 있습니다.

**쿼리 힌트 없음**  
다음 SPARQL 쿼리는 4개의 홉을 통해 서로 주기적으로 연결된 모든 `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 쿼리 엔진의 접근 방식은 다음 단계를 사용하여 이 쿼리를 평가하는 것입니다.
+ 그래프에서 1,000개의 `connectedTo` 엣지를 모두 추출합니다.
+ 100x(component2에서 발신 `connectedTo` 엣지의 수)로 확장합니다.

  중간 결과: 100,000개 노드
+ 100x(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을 실행할 때 이 2개의 100,000개 하위 세트를 주 메모리에 임시로 저장하면 평가 속도가 크게 빨라져 메모리 사용이 늘어납니다.

# `queryTimeout` SPARQL 쿼리 힌트
<a name="sparql-query-hints-queryTimeout"></a>

`queryTimeout` 쿼리 힌트는 DB 파라미터 그룹에 설정된 `neptune_query_timeout` 값보다 작은 제한 시간을 지정합니다.

이 힌트의 결과로 쿼리가 종료되면 `Operation terminated (deadline exceeded)` 메시지와 함께 `TimeLimitExceededException`이 발생합니다.

## `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 .
 ...
}
```

제한 시간 값은 밀리초로 표시됩니다.

제한 시간 값은 DB 파라미터 그룹에 설정된 `neptune_query_timeout` 값보다 작아야 합니다. 그렇지 않으면 `Malformed query: Query hint 'queryTimeout' must be less than neptune_query_timeout DB Parameter Group` 메시지와 함께 `MalformedQueryException` 예외가 발생합니다.

`queryTimeout` 쿼리 힌트는 아래 예제에 표시된 대로 주 쿼리의 `WHERE` 절 또는 하위 쿼리 중 하나의 `WHERE` 절에 지정되어야 합니다.

모든 쿼리/하위 쿼리 및 SPARQL 업데이트 섹션(예: INSERT 및 DELETE)에서 한 번만 설정해야 합니다. 그렇지 않으면 `Malformed query: Query hint 'queryTimeout' must be set only once` 메시지와 함께 `MalformedQueryException` 예외가 발생합니다.

**사용 가능한 범위**

`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`(기본값) 값도 사용할 수 있습니다.

**예제.** 다음 예제는 1보다 큰 `o` 정수 값을 필터링할 때 유형 승격을 비활성화하는 방법을 보여줍니다.

```
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>

이 쿼리 힌트를 사용해 SPARQL 쿼리에 자체 queryld 값을 할당합니다.

예제:

```
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 DB의 모든 쿼리에서 고유해야 합니다.

# `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 .
```

참고로 DESCRIBE 쿼리는 입력 데이터 세트와 비교하여 매번 ID가 다른 빈 노드가 있는 트리플을 반환할 수 있습니다(예: `_:b301990159`).

### `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 .
```

`ForwardOneStep` 및 `SymmetricOneStep` 모드에 비해 CBD와 SCBD의 장점은 빈 노드가 항상 해당 표현을 포함하도록 확장된다는 것입니다. 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 쿼리 힌트는 CBD 및 SCBD와 같은 반복적 DESCRIBE 알고리즘에 대해 수행할 최대 반복 확장 횟수에 대한 **선택적** 제약 조건을 제공합니다.

DESCRIBE 제한은 AND로 연결됩니다. 따라서 반복 제한과 문 제한을 둘 다 지정하는 경우 DESCRIBE 쿼리를 끊기 전에 두 제한을 모두 충족해야 합니다.

이 값의 기본값은 5입니다. 이 값을 0으로 설정하여 반복 확장 횟수에 제한을 두지 않도록 지정할 수 있습니다.

## `describeStatementLimit` SPARQL 쿼리 힌트
<a name="sparql-query-hints-describeStatementLimit"></a>

`hint:describeStatementLimit` SPARQL 쿼리 힌트는 DESCRIBE 쿼리 응답에 존재할 수 있는 최대 문 수에 대한 **선택적** 제약 조건을 제공합니다. CBD 및 SCBD와 같은 반복적인 DESCRIBE 알고리즘에만 적용됩니다.

DESCRIBE 제한은 AND로 연결됩니다. 따라서 반복 제한과 문 제한을 둘 다 지정하는 경우 DESCRIBE 쿼리를 끊기 전에 두 제한을 모두 충족해야 합니다.

이 값의 기본값은 5,000입니다. 반환되는 문 수에 제한을 두지 않도록 지정하려면 이 값을 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은 `DESCRIBE`가 사용할 수 있는 다양한 모드와 알고리즘을 간접적으로 호출하는 [몇 가지 쿼리 힌트](sparql-query-hints-for-describe.md)를 제공합니다.

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` 절이 없는 `FROM NAMED` 절이 있으면 기본 그래프가 비어 있기 때문입니다.

다음 쿼리에서 `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 쿼리의 수입니다.

**쿼리**  
현재 SPARQL 쿼리의 목록입니다.

**queryId**  
쿼리의 GUID id. Neptune이 ID 값을 각 쿼리에 자동 할당하거나 사용자가 자체 ID를 할당할 수 있습니다([Neptune Gremlin 또는 SPARQL 쿼리에 사용자 지정 ID 주입](features-query-id.md) 참조).

**queryEvalStats**  
이 쿼리에 대한 통계.

**하위 쿼리**  
이 쿼리에 있는 하위 쿼리의 수.

**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=true`이면 실행 중인 쿼리가 취소되고 HTTP 응답 코드가 200이 됩니다. `silent`가 존재하지 않거나 `silent=false`인 경우에는 HTTP 500 상태 코드를 통해 쿼리가 취소됩니다.

## SPARQL 쿼리 취소 예제
<a name="sparql-api-status-cancel-example"></a>

**예제 1: `silent=false`을 통한 취소**  
다음은 `silent` 파라미터가 `false`으로 설정된 상태에서 쿼리를 취소하기 위해 `curl`을 사용하는 상태 명령의 예제입니다.

```
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에 지정된 명명된 그래프를 추가하거나 업데이트합니다.

예를 들어, 빈 데이터베이스에서 시작하여 투표를 3개의 그래프로 정리해 달라는 `PUT` 요청을 보낸다고 가정해 보겠습니다. `urn:votes`라는 이름의 1개에는 모든 선거 연도의 모든 투표가 포함되어 있습니다. `urn:votes:2005` 및 `urn:votes:2019`라는 이름의 다른 2개에는 특정 선거 연도의 투표가 포함되어 있습니다. 요청과 페이로드는 다음과 같습니다.

```
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>
```

또 다른 모호한 상황은 `PUT`, `POST`, `GET`, `DELETE` 중 하나를 사용하여 요청 URL 자체에 둘 이상의 그래프를 지정하는 경우입니다. 예제:

```
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은 요청 URL에 그래프를 하나만 지정할 수 있다는 메시지와 함께 HTTP 400을 반환합니다.

# SPARQL `explain`을 사용하여 Neptune 쿼리 실행 분석
<a name="sparql-explain"></a>

Amazon Neptune에는 *Explain*이라는 SPARQL 기능이 추가되었습니다. 이 기능은 Neptune 엔진에 의해 수행되는 실행 접근 방식을 이해하기 위한 셀프 서비스 도구입니다. SPARQL 쿼리를 제출하는 HTTP 호출에 `explain` 파라미터를 추가하여 이 도구를 호출합니다.

`explain` 기능은 쿼리 실행 계획의 논리 구조에 대한 정보를 제공합니다. 이 정보를 사용하여 잠재적 평가 및 실행 병목 현상을 파악합니다. 그런 다음 [쿼리 힌트](sparql-query-hints.md)를 사용하여 쿼리 실행 계획을 개선할 수 있습니다.

**Topics**
+ [Neptune에서 SPARQL 쿼리 엔진 작동 방식](sparql-explain-engine.md)
+ [SPARQL `explain`을 사용하여 Neptune 쿼리 실행을 분석하는 방법](sparql-explain-using.md)
+ [Neptune에서 SPARQL `explain`을 간접 호출하는 예제](sparql-explain-examples.md)
+ [Neptune SPARQL `explain` 연산자](sparql-explain-operators.md)
+ [Neptune에서 SPARQL `explain` 제한](sparql-explain-limitations.md)

# Neptune에서 SPARQL 쿼리 엔진 작동 방식
<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`은 다음과 같은 3개의 조회를 평가합니다.

```
  (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` 기능은 Neptune 엔진에 의해 수행되는 실행 접근 방식을 이해하는 데 도움이 되는 Amazon Neptune의 셀프 서비스 도구입니다. `explain`을 호출하려면 `explain=mode` 형식으로 파라미터를 HTTP 또는 HTTPS 요청에 전달합니다.

모드 값은 `static`, `dynamic`, `details` 중 하나일 수 있습니다.
+ *정적* 모드에서 `explain`은 쿼리 계획의 정적 구조만 인쇄합니다.
+ *동적* 모드에서 `explain`은 쿼리 계획의 동적 측면도 포함합니다. 이러한 측면에는 연산자를 통해 진행되는 중간 바인딩의 수, 수신 바인딩과 발신 바인딩의 비율, 연산자에 소요된 총 시간이 포함됩니다.
+ *세부* 모드에서 `explain`은 `dynamic` 모드로 표시된 정보와 조인 연산자의 기본 패턴에 대한 실제 SPARQL 쿼리 문자열 및 예상 범위 수와 같은 추가 세부 정보를 인쇄합니다.

Neptune은 다음과 같이 [W3C SPARQL 1.1 프로토콜](https://www.w3.org/TR/sparql11-protocol/#query-operation) 사양에 나열된 3가지 SPARQL 쿼리 액세스 프로토콜과 함께 `explain`을 사용할 수 있도록 지원합니다.

1. HTTP GET

1. URL로 인코딩한 파라미터를 사용하는 HTTP POST

1. 텍스트 파라미터를 사용하는 HTTP POST

SPARQL 쿼리 엔진에 대한 자세한 내용은 [Neptune에서 SPARQL 쿼리 엔진 작동 방식](sparql-explain-engine.md) 단원을 참조하십시오.

SPARQL `explain` 호출을 통해 생성된 출력의 종류에 대한 자세한 내용은 [Neptune에서 SPARQL `explain`을 간접 호출하는 예제](sparql-explain-examples.md) 단원을 참조하십시오.

# Neptune에서 SPARQL `explain`을 간접 호출하는 예제
<a name="sparql-explain-examples"></a>

이 섹션의 예제는 Amazon Neptune에서 쿼리 실행을 분석하기 위해 SPARQL `explain` 기능을 간접적으로 호출하여 생성할 수 있는 다양한 종류의 출력을 보여줍니다.

**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` 대신 기본 출력 유형을 사용하여 `explain`을 호출하도록 `curl` 명령을 변경합니다.

```
 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`은 이러한 내부 식별자의 매핑을 해당하는 조건 문자열로 다시 수행합니다.

   일반(비 Explain) 쿼리 평가의 경우 최종 연산자에 의해 계산된 결과는 요청된 직렬화 형식으로 직렬화되고 클라이언트로 스트리밍됩니다.

## 세부 모드 출력의 예제
<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"
```

이 예제에 표시된 대로 출력은 동일하지만, 마지막 3개의 열이 생략됩니다.

```
╔════╤════════╤════════╤═══════════════════╤═══════════════════════════════════════════════════════╤══════════╗
║ 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은 SPARQL `explain` 출력을 다른 두 MIME 유형 형식, 즉 `text/csv` 및 `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/ko_kr/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>

지정된 모드에서 지정한 대로 솔루션 스트림을 위임합니다.

**Modes**
+ `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` – (*선택 사항*) `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 형식이며, 경우에 따라 조인의 기반이 되는 -graph 튜플입니다. 패턴에 대해 `distinct`가 지정되면 조인은 일치하는 모든 솔루션이 아닌 `projectionVars` 인수로 지정된 프로젝션 변수의 개별 솔루션만 추출합니다.
+ `inlineFilters` – (*선택 사항*) 패턴의 변수에 적용할 필터 세트입니다. 패턴은 이러한 필터와 함께 평가됩니다.
+ `joinType` – (*필수*) 수행할 조인 유형입니다.
  + `join` – 정상 조인이며, 공유된 모든 변수 간 정확하게 일치해야 합니다.
  + `optional` - `optional` 조인으로, SPARQL `OPTIONAL` 연산자 의미 시맨틱을 사용합니다.
  + `minus` – `minus` 작업은 조인 파트너가 없는 매핑을 유지하며, SPARQL `MINUS` 연산자 의미 시맨틱을 사용합니다.
  + `existence check` – 조인 파트너가 있는지 여부를 확인하며, `existenceCheckResultVar` 변수를 이 확인 결과에 바인딩합니다.
+ `constraints` – (*선택 사항*) 조인 중 고려되는 추가 조인 제약 조건입니다. 이러한 제약 조건을 충족하지 않는 조인은 삭제됩니다.
+ `projectionVars` – (*선택 사항*) 프로젝션 변수입니다. `distinct := true`와 함께 사용되어 지정된 변수 집합에 대해 개별 프로젝션을 추출합니다.
+ `cutoffLimit` – (*선택 사항*) 추출된 조인 파트너의 수에 대한 차단 제한입니다. 기본적으로는 제한이 없지만, `FILTER (NOT) EXISTS` 절을 구현하기 위해 조인을 수행할 때 이 값을 1로 설정할 수 있습니다. 1은 조인 파트너가 있음을 증명하거나 반증하기에 충분합니다.

## `PipelineCountJoin` 연산자
<a name="sparql-explain-operator-pipeline-count-join"></a>

`PipelineJoin`의 변형입니다. 조인하는 대신 일치하는 조인 파트너를 계수하고 해당 개수를 `countVar` 인수로 지정된 변수에 바인딩합니다.

**인수**
+ `countVar` – (*필수*) 주로 조인 파트너의 수인 개수 결과를 바인딩할 변수입니다.
+ `pattern` – (*필수*) subject-predicate-object 형식이며, 경우에 따라 조인의 기반이 되는 -graph 튜플입니다. 패턴에 대해 `distinct`가 지정되면 조인은 일치하는 모든 솔루션이 아닌 `projectionVars` 인수로 지정된 프로젝션 변수의 개별 솔루션만 추출합니다.
+ `inlineFilters` – (*선택 사항*) 패턴의 변수에 적용할 필터 세트입니다. 패턴은 이러한 필터와 함께 평가됩니다.
+ `joinType` – (*필수*) 수행할 조인 유형입니다.
  + `join` – 정상 조인이며, 공유된 모든 변수 간 정확하게 일치해야 합니다.
  + `optional` - `optional` 조인으로, SPARQL `OPTIONAL` 연산자 의미 시맨틱을 사용합니다.
  + `minus` – `minus` 작업은 조인 파트너가 없는 매핑을 유지하며, SPARQL `MINUS` 연산자 의미 시맨틱을 사용합니다.
  + `existence check` – 조인 파트너가 있는지 여부를 확인하며, `existenceCheckResultVar` 변수를 이 확인 결과에 바인딩합니다.
+ `constraints` – (*선택 사항*) 조인 중 고려되는 추가 조인 제약 조건입니다. 이러한 제약 조건을 충족하지 않는 조인은 삭제됩니다.
+ `projectionVars` – (*선택 사항*) 프로젝션 변수입니다. `distinct := true`와 함께 사용되어 지정된 변수 집합에 대해 개별 프로젝션을 추출합니다.
+ `cutoffLimit` – (*선택 사항*) 추출된 조인 파트너의 수에 대한 차단 제한입니다. 기본적으로는 제한이 없지만, `FILTER (NOT) EXISTS` 절을 구현하기 위해 조인을 수행할 때 이 값을 1로 설정할 수 있습니다. 1은 조인 파트너가 있음을 증명하거나 반증하기에 충분합니다.

## `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>

변수의 하위 집합에 대해 프로젝션합니다. 유입되는 솔루션의 수는 유출되는 솔루션의 수와 같지만, 솔루션의 형태는 모드 설정에 따라 달라집니다.

**Modes**
+ `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>

모드에 따라 내부 문자열 식별자 값을 해당하는 외부 문자열로 변환하거나, 외부 문자열을 내부 문자열 식별자 값으로 변환합니다.

**Modes**
+ `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` 정보를 알아보려면 `SELECT WHERE {...} LIMIT 1` 쿼리를 `explain`과 함께 실행합니다.

마찬가지로, `CONSTRUCT {...} WHERE {...}` 쿼리의 경우 `CONSTRUCT {...}` 부분을 삭제하고 두 번째 `WHERE {...}` 절에서 `SELECT` 쿼리를 `explain`과 함께 실행합니다. 두 번째 `WHERE`에서 `CONSTRUCT` 템플릿으로 진행되는 솔루션에는 일반적으로 간단한 대체만 필요하므로 두 번째 `WHERE` 절을 평가하면 일반적으로 `CONSTRUCT` 쿼리 처리의 주요 문제점을 알 수 있습니다.

**향후 릴리스에서 Explain 연산자가 변경될 수 있음**  
SPARQL `explain` 연산자와 해당 파라미터가 향후 릴리스에서 변경될 수 있습니다.

**향후 릴리스에서 Explain 출력이 변경될 수 있음**  
예를 들어, 열 헤더가 변경될 수 있으며 테이블에 더 많은 열이 추가될 수 있습니다.

# `SERVICE` 확장을 사용하는 Neptune의 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은 Virtual Private Cloud(VPC) 내에서 액세스할 수 있는 SPARQL 엔드포인트에 대해서만 페더레이션 쿼리를 실행할 수 있습니다. 그러나 VPC에서 리버스 프록시를 사용하여 VPC 내에서 외부 데이터 소스에 액세스할 수 있게 하는 것도 가능합니다.

**참고**  
SPARQL `SERVICE`를 사용하여 동일한 VPC에 있는 2개 이상의 Neptune 클러스터에 쿼리를 페더레이션하는 경우 모든 Neptune 클러스터가 서로 통신할 수 있도록 보안 그룹을 구성해야 합니다.

**중요**  
SPARQL 1.1 Federation은 외부 SPARQL 엔드포인트에 쿼리 및 파라미터를 전달할 때 사용자를 대신해 서비스 요청을 수행합니다. 외부 SPARQL 엔드포인트가 애플리케이션의 데이터 처리 및 보안 요구 사항을 충족하는지 확인하는 것은 사용자의 책임입니다.

## Neptune 페더레이션 쿼리의 예제
<a name="sparql-service-example-1"></a>

다음은 SPARQL 연동 쿼리가 어떻게 작동하는지 보여주는 간단한 예제입니다.

고객이 `http://neptune-1:8182/sparql`에서 *Neptune-1*에 다음과 같은 쿼리를 보낸다고 가정해 보겠습니다.

```
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`을 해결한 다음, 결과 패턴을 `http://neptune-2:8182/sparql`의 *Neptune-2*에 전달합니다.

1. *Neptune-2*는 *Q-2*를 평가하고 그 결과를 *Neptune-1*에 다시 전송합니다.

1. *Neptune-1*은 두 패턴 모두에 대한 솔루션을 조인하여 결과를 고객에게 다시 전송합니다.

이 흐름은 다음 다이어그램에 나와 있습니다.

![\[평가 중인 SPARQL 연동 쿼리 패턴과 클라이언트에 다시 전송된 응답을 보여주는 흐름 다이어그램.\]](http://docs.aws.amazon.com/ko_kr/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 DB 인스턴스가 하나 이상 관여할 수 있습니다. 이들 인스턴스는 액세스 제어에 대한 요구 사항이 서로 다를 수 있습니다. 어떤 경우에는 이로 인해 연동 쿼리를 구성하는 능력이 제한될 수 있습니다.

이전 섹션에 제시된 간단한 예를 생각해 봅시다. *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*에 전달하여 쿼리의 두 번째 부분에 대해 권한을 부여할 수 없기 때문입니다.