API를 사용하여 인덱스 생성
SQL 명령 사용
인덱스는 CREATE INDEX
명령을 사용하여 생성할 수 있습니다.
단일 필드 인덱스 생성:
CREATE INDEX fixedschema_conf ON baggageInfo(confNo)
위의 예제는 단일 열 고정 스키마 인덱스의 예입니다. 인덱스는 baggageInfo
테이블에 string
데이터 유형이 있는 confNo
필드에 생성됩니다.
조합 인덱스 생성:
CREATE INDEX compindex_namephone ON baggageInfo(fullName,contactPhone)
주:
이 인덱스의 필드를 하나 이상 고정 스키마 열로 지정할 수 있습니다.JSON 인덱스를 생성합니다.
하나 이상의 필드가 JSON 데이터 내에 있는 경우 인덱스를 JSON 인덱스라고 합니다. JSON은 스키마가 없으므로 인덱스화된 JSON 필드의 데이터 유형은 행마다 다를 수 있습니다. JSON 필드에 인덱스를 생성할 때 JSON 필드에 필요한 데이터 유형이 확실하지 않으면 anyAtomic 데이터 유형을 사용할 수 있습니다. 또는 Oracle NoSQL Database 기본 데이터 유형 중 하나를 지정할 수 있습니다. 이렇게 하려면 모든 인덱스 경로 옆에 있는 AS 키워드를 사용하여 JSON 필드에 데이터 유형을 선언합니다.
CREATE INDEX jsonindex_tagnum ON baggageInfo(bagInfo[].tagnum as INTEGER)
위는 JSON 인덱스의 예입니다. 인덱스는 baggageInfo
테이블의 baginfo
JSON 필드에 있는 tagnum
필드에 생성됩니다. 인덱스를 생성하는 동안 tagnum
필드에 데이터 유형을 제공합니다.
연관된 테이블에 선언된 데이터 유형을 위반하는 데이터가 있는 행이 있을 경우 JSON 인덱스 생성이 실패합니다. 마찬가지로 JSON 인덱스를 생성한 후 새 행이 JSON 인덱스의 선언된 데이터 유형을 준수하지 않으면 삽입/업데이트 작업이 실패합니다.
CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)
- 숫자
- String
- boolean
그러나 이러한 장점은 공간 및 CPU 비용으로 상쇄됩니다. 인덱스에 저장되기 전에 인덱스화된 필드에서 모든 종류의 숫자 값이 숫자로 변환되기 때문입니다. 이 데이터형 변환에는 CPU 시간이 걸리며 결과적으로 숫자에 대한 저장소가 숫자에 대한 원래 저장소보다 큽니다.
단순 인덱스 생성:
테이블의 각 데이터 행에 대해 인덱스에 생성된 항목이 하나 있는 경우 인덱스를 단순 인덱스라고 합니다. 인덱스는 원자 데이터 유형 또는 특수 값(SQL NULL, JSON NULL, EMPTY)인 단일 값을 반환합니다. 기본적으로 단순 인덱스의 인덱스 경로는 배열이나 맵 또는 중첩된 데이터 유형을 반환하지 않아야 합니다.
CREATE INDEX simpleindex_arrival ON baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
bagInfo[].bagArrivalDate as ANYATOMIC, bagInfo[].lastSeenTimeStation as ANYATOMIC)
위의 예는 JSON 필드에서 JSON 문서에 생성된 단순 인덱스의 예입니다. 인덱스는 baggageInfo
테이블의 정보 JSON 필드에 있는 bagInfo
JSON 문서에서 모두 lastSeenTimeGmt
및 bagArrivalDate
및 lastSeenTimeStation
에 생성됩니다. 단순 인덱스 경로 평가에서 빈 결과를 반환하면 특수 값 EMPTY가 인덱스 항목으로 사용됩니다. 위의 예에서 bagInfo
JSON 문서에 lastSeenTimeGmt
또는 bagArrivalDate
또는 lastSeenTimeStation
항목이 없거나 bagInfo
JSON 배열이 없는 경우 특수 값 EMPTY가 인덱스화됩니다.
다중 키 인덱스 생성:
테이블의 각 데이터 행에 대해 인덱스에 생성된 다중 항목이 있는 경우 인덱스를 다중 키 인덱스라고 합니다. 다중 키 인덱스에는 배열 또는 중첩 데이터 유형을 사용하는 인덱스 경로가 하나 이상 있습니다. 다중 키 인덱스에서는 각 테이블 행에 대해 인덱스화되는 배열의 모든 요소에 대해 인덱스 항목이 생성됩니다.
CREATE INDEX multikeyindex1 ON stream_acct (acct_data.contentStreamed[].seriesInfo[] AS ANYATOMIC)
인덱스는 stream_acct 테이블의 seriesInfo[]
배열에 생성됩니다. 여기서 stream_acct
테이블의 각 행에 있는 seriesInfo[]
배열의 모든 요소가 인덱스화됩니다.
예 2: 중첩된 다중 키 인덱스: 스트리밍 계정 응용 프로그램의 에피소드 세부 정보 배열에 인덱스를 생성합니다.
CREATE INDEX multikeyindex2 ON stream_acct (
acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)
위는 다른 배열 안에 있는 배열에 필드가 있는 중첩된 다중 키 인덱스의 예입니다. 인덱스는 stream_acct
테이블의 acct_data
JSON에 있는 seriesInfo[]
배열의 episodes[]
배열에 생성됩니다.
예제 3: 조합 다중 키 인덱스:
CREATE INDEX multikeyindex3 ON stream_acct (acct_data.country AS ANYATOMIC,
acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)
위의 예제는 하나의 다중 키 인덱스 경로와 하나의 단순 인덱스 경로를 갖는 조합 다중 키 인덱스의 예입니다. 인덱스는 country
필드에 생성되고 stream_acct
테이블의 acct_data
JSON 열에 episodes[]
array가 생성됩니다.
다중 키 인덱스에 대한 제한 사항에 대해 알아보려면 Specifications & Restrictions on Multikey index을 참조하십시오.
NO NULLS 절을 사용하여 인덱스 생성
CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS
- 위 질의는 승객의 전화 번호에 대한 인덱스를 생성합니다. 일부 승객에게 전화 번호가 없으면 해당 필드는 인덱스에 포함되지 않습니다.
- WITH NO NULLS 절을 사용하여 생성되는 인덱스는 데이터가 인덱스화된 필드에 많은 NULL 및/또는 EMPTY 값을 포함하는 경우에 유용할 수 있습니다. 인덱스화 중에 발생하는 시간과 공간 오버헤드를 줄입니다.
- 그러나 query에 의한 인덱스 사용은 제한됩니다. WITH NO NULLS 절을 사용하여 인덱스를 생성한 경우 IS NULL 및 NOT EXISTS 술어는 해당 인덱스에 대한 인덱스 술어로 사용할 수 없습니다.
- 실제로 이러한 인덱스는 query에 인덱스화된 각 필드에 대한 인덱스 술어가 있는 경우에만 query에 사용될 수 있습니다.
행당 고유 키로 인덱스 생성
CREATE INDEX idx_showid ON
stream_acct(acct_data.contentStreamed[].showId AS INTEGER)
WITH UNIQUE KEYS PER ROW
위의 질의에서 인덱스는 showId
에 생성되며 단일 contentStreamed
배열에 대해 중복 showId
가 있을 수 없습니다. 스트리밍 사용자의 경우 contentStreamed
배열에 동일한 표시 ID를 가진 둘 이상의 표시가 포함될 수 없음을 질의 프로세서에 알립니다. 중복 표시 ID가 있을 경우 인덱스에 포함되지 않으므로 제한이 필요합니다. 단일 contentStreamed
배열에 동일한 showId
항목이 있는 행을 두 개 이상 삽입하면 오류가 발생하고 삽입 작업이 실패합니다.
Query 런타임 최적화:
행당 고유 키로 인덱스를 생성할 때 인덱스는 contentStreamed
배열의 요소 수보다 적은 항목을 포함합니다. 이 인덱스를 사용하는 효율적인 query를 작성할 수 있습니다. 질의에서 이러한 인덱스를 사용하면 인덱스를 사용하지 않은 경우보다 FROM 절에서 더 적은 결과가 나옵니다.
함수에 대한 인덱스 생성 예제:
BaggageInfo
테이블의 행을 인덱스화하는 인덱스를 생성합니다.CREATE INDEX idx_modtime ON BaggageInfo(modification_time())
modification_time
가 있는 질의에 사용됩니다.SELECT * FROM BaggageInfo $u WHERE
modification_time($u) > "2019-08-01T10:45:00"
이 질의는 가장 최근 수정 시간이 2019-08-01T10:45:00 이후인 모든 행을 반환합니다. 위에 정의된 idx_modtime
인덱스를 사용합니다. show query
명령을 사용하여 질의 계획을 확인하여 이를 확인할 수 있습니다.
BaggageInfo
테이블의 행을 인덱스화하는 인덱스를 생성합니다.CREATE INDEX idx_routlen ON BaggageInfo (length(bagInfo[].routing as string))
length
가 있는 질의에 사용됩니다.SELECT * from BaggageInfo $bag where length($bag.bagInfo[].routing) > 10
이 질의는 경로 지정 필드의 길이가 10보다 큰 모든 행을 반환합니다. 위에 정의된 idx_routlen
인덱스를 사용합니다. show query
명령을 사용하여 질의 계획을 확인하여 이를 확인할 수 있습니다.
예 3: 다중 키 인덱스 경로 사용
stream_acct
테이블의 사용자를 자신이 보는 쇼의 ID와 쇼가 시청된 날짜의 연도 및 월로 인덱스화합니다.CREATE INDEX idx_showid_year_month ON
stream_acct(acct_data.contentStreamed[].showId AS INTEGER,
substring(acct_data.contentStreamed[].seriesInfo[].episodes[].date AS STRING,0, 4),
substring(acct_data.contentStreamed[].seriesInfo[].episodes[].date AS STRING,5, 2))
SELECT count(*) FROM stream_acct s1 WHERE EXISTS
s1.acct_data.contentStreamed[$element.showId = 16].seriesInfo.
episodes[substring($element.date, 0, 4) = "2022"]
idx_showid_year_month
인덱스를 사용합니다. show query
명령을 사용하여 질의 계획을 확인하여 이를 확인할 수 있습니다.show query SELECT count(*) FROM stream_acct s1 WHERE EXISTS
> s1.acct_data.contentStreamed[$element.showId = 16].seriesInfo.episodes[substring($element.date, 0, 4) = "2022"]
{
"iterator kind" : "GROUP",
"input variable" : "$gb-1",
"input iterator" :
{
"iterator kind" : "RECEIVE",
"distribution kind" : "ALL_SHARDS",
"distinct by fields at positions" : [ 1 ],
"input iterator" :
{
"iterator kind" : "SELECT",
"FROM" :
{
"iterator kind" : "TABLE",
"target table" : "stream_acct",
"row variable" : "$$s1",
"index used" : "idx_showid_year_month",
"covering index" : true,
"index row variable" : "$$s1_idx",
"index scans" : [
{
"equality conditions" : {"acct_data.contentStreamed[].showId":16,"substring#acct_data.contentStreamed[].seriesInfo[].episodes[].date@,0,4":"2022"},
"range conditions" : {}
}
]
},
"FROM variable" : "$$s1_idx",
"SELECT expressions" : [
{
"field name" : "Column_1",
"field expression" :
{
"iterator kind" : "CONST",
"value" : 1
}
},
{
"field name" : "acct_id_gen",
"field expression" :
{
"iterator kind" : "FIELD_STEP",
"field name" : "#acct_id",
"input iterator" :
{
"iterator kind" : "VAR_REF",
"variable" : "$$s1_idx"
}
}
}
]
}
},
"grouping expressions" : [
],
"aggregate functions" : [
{
"iterator kind" : "FUNC_COUNT_STAR"
}
]
}
TableRequest API 사용
TableRequest API를 사용하여 NoSQL 테이블에 인덱스를 생성할 수 있습니다.
TableRequest
클래스는 테이블에 인덱스를 생성하는 데 사용됩니다. 이 요청에 의해 지정된 작업의 실행은 비동기입니다. 이러한 작업은 장기적으로 실행될 수 있습니다. TableResult
는 TableRequest
작업에서 반환되며 테이블의 상태를 캡슐화합니다. TableRequest
클래스 및 해당 메소드에 대한 자세한 내용은 Oracle NoSQL Java SDK API Reference를 참조하십시오.
/**
* Create an index acct_episodes in the stream_acct table
*/
private static void crtIndex(NoSQLHandle handle) throws Exception {
String createIndexDDL = "CREATE INDEX acct_episodes ON " + tableName +
"(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)";
TableRequest treq = new TableRequest().setStatement(createIndexDDL);
TableResult tres = handle.tableRequest(treq);
tres.waitForCompletion(handle, 60000, /* wait 60 sec */
1000); /* delay ms for poll */
System.out.println("Index acct_episodes on " + tableName + " is created");
}
borneo.TableRequest
클래스는 테이블에 인덱스를 생성하는 데 사용됩니다. borneo.NoSQLHandle.table_request()
에 대한 모든 호출은 비동기적이므로 결과를 확인하고 작업이 완료될 때까지 기다리려면 borneo.TableResult.wait_for_completion()
를 호출해야 합니다. table_request
및 해당 메소드에 대한 자세한 내용은 Oracle NoSQL Python SDK API Reference를 참조하십시오.
#create an index
def create_index(handle):
statement = '''CREATE INDEX acct_episodes ON stream_acct (acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)'''
request = TableRequest().set_statement(statement)
table_result = handle.do_table_request(request, 40000, 3000)
table_result.wait_for_completion(handle, 40000, 3000)
print('Index acct_episodes on the table stream_acct is created')
TableRequest
클래스는 테이블에 인덱스를 생성하는 데 사용됩니다. TableRequest
로 지정된 작업의 실행은 비동기입니다. 이러한 작업은 장기적으로 실행될 수 있습니다. 이 요청은 Client.DoTableRequest()
작업의 입력으로 사용되며, 테이블이 원하는 상태에 도달할 때까지 폴링에 사용할 수 있는 TableResult
를 반환합니다. TableRequest
클래스의 다양한 메소드에 대한 자세한 내용은 Oracle NoSQL Go SDK API Reference를 참조하십시오.
//create an index on a table
func createIndex(client *nosqldb.Client, err error, tableName string)(){
stmt := fmt.Sprintf("CREATE INDEX acct_episodes ON %s "+
"(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)",tableName)
tableReq := &nosqldb.TableRequest{
Statement: stmt,
}
tableRes, err := client.DoTableRequest(tableReq)
if err != nil {
fmt.Printf("cannot initiate CREATE INDEX request: %v\n", err)
return
}
// The create index request is asynchronous, wait for index creation to complete.
_, err = tableRes.WaitForCompletion(client, 60*time.Second, time.Second)
if err != nil {
fmt.Printf("Error finishing CREATE INDEX request: %v\n", err)
return
}
fmt.Println("Created Index acct_episodes on table ", tableName)
return
}
tableDDL
메소드를 사용하여 테이블에 인덱스를 생성할 수 있습니다. 이 메소드는 비동기적이며 Promise TableResult
를 반환합니다. TableResult
는 테이블 상태를 캡슐화하는 일반 JavaScript 객체입니다. 메소드 세부 정보는 NoSQLClient 클래스를 참조하십시오.
//creates an index
async function createIndex(handle) {
const crtindDDL = `CREATE INDEX acct_episodes ON ${TABLE_NAME}(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)`;
let res = await handle.tableDDL(crtindDDL);
console.log('Index acct_episodes is created on table:' + TABLE_NAME);
}
테이블에 인덱스를 생성하려면 ExecuteTableDDLAsync
또는 ExecuteTableDDLWithCompletionAsync
메소드를 사용합니다. 이 두 메소드는 모두 Task<TableResult>
를 반환합니다. TableResult
인스턴스는 TableState 및 테이블 스키마와 같은 DDL 작업의 상태를 포함합니다. 이러한 방법에 대한 자세한 내용은 Oracle NoSQL Dotnet SDK API Reference를 참조하십시오.
// Creates an index on a table
private static async Task createIndex(NoSQLClient client){
var sql =
$@"CREATE INDEX acct_episodes ON {TableName}(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)";
var tableResult = await client.ExecuteTableDDLAsync(sql);
// Wait for the operation completion
await tableResult.WaitForCompletionAsync();
Console.WriteLine(" Index acct_episodes is created on table Table {0}",
tableResult.TableName);
}