카우치베이스 서버 사용 4.0 GA - 민첩하게 개발하고 대규모로 운영할 수 있는 핵심 요소인 N1QL을 제공했습니다! 이제, 저희는 기쁜 마음으로 4.1 개발자 프리뷰 릴리스 - 중요한 안정성 수정 사항이 포함되어 있습니다. 그 안에는 커버링 인덱스라는 핵심 기능이 포함되어 있습니다.
커버링 인덱스는 4.1 릴리즈의 새로운 N1QL 기능으로, 이를 적절히 활용하는 애플리케이션이 많은 경우 눈에 띄는 쿼리 성능 향상을 인식할 수 있는 기능을 제공합니다. 커버링 쿼리는 쿼리의 모든 필드가 인덱스의 일부이고 쿼리에서 반환되는 모든 필드가 동일한 인덱스에 있는 N1QL 쿼리입니다.
이번 개선 전의 쿼리 실행 흐름을 살펴보면 다음과 같습니다:
-
애플리케이션 클라이언트는 Rest API를 통해 서버에 쿼리 요청을 발행합니다.
-
쿼리 서비스는 구문 분석 및 분석 단계를 거쳐 쿼리 계획을 생성합니다.
-
쿼리 서비스는 상황에 맞는 유효한 인덱스가 있는 경우 인덱스 서비스에 스캔 요청을 발행합니다.
-
색인 서비스에서 적격 문서 키를 가져옵니다.
-
문서 키를 데이터 서비스로 전송('가져오기 요청')합니다.
-
데이터 서비스에서 문서를 다시 가져옵니다.
-
문서를 평가합니다(필터 기준 재적용 등).
-
최종 필터링된 결과를 클라이언트로 다시 전송합니다.
잘 설계된 애플리케이션에서는 커버링 인덱스를 사용하여 5단계와 6단계를 피할 수 있으며(권장하는 모범 사례), 이를 통해 눈에 띄는 성능 개선 효과를 얻을 수 있습니다.
N1QL의 EXPLAIN 문을 사용하면 쿼리 실행 계획을 확인할 수 있습니다. 커버링 인덱스가 쿼리 실행에 사용되는 경우, 이제 EXPLAIN에 데이터 액세스에 커버링 인덱스가 사용됨이 표시됩니다(키-값 문서 가져오기 및 관련 오버헤드가 피할 수 있음).
맥주 샘플 버킷의 'state' 속성에 대한 인덱스를 생성한다고 가정해 보겠습니다.
CREATE INDEX idxstate ON 맥주 샘플(상태) GSI 사용
이제 맥주 샘플에서 state를 선택하면 반환할 모든 데이터가 인덱스에 있으므로 키-값 데이터 가져오기를 피하고 인덱스에 기반한 데이터만 반환할 수 있습니다.
설명 SELECT 상태 FROM beer-sample' WHERE state = "CA"
"결과": [
{
"1TP5운영자": "시퀀스",
"~어린이": [
{
"1TP5운영자": "IndexScan",
"커버": [
"cover((맥주 샘플.상태))"
],
"index": "idxstate",
"키스페이스": "맥주 샘플",
"네임스페이스": "기본값",
"스팬": [
{
"범위": {
"높음": [
""CA""
],
"포함": 3,
"낮음": [
""CA""
]
}
}
],
"사용": "gsi"
참고: 쿼리가 약간 수정되는 경우 동일한 인덱스는 커버링 인덱스가 아닙니다.
설명 SELECT 주, 도시 FROM 맥주 샘플 여기서 state = "ca";
여전히 idxstate 인덱스를 사용하지만 인덱스에 도시 정보가 포함되어 있지 않으므로 빠른 조회를 위해 인덱스를 사용하지만 커버링 인덱스로는 사용하지 않습니다.
{
"요청ID": "c60b10d2-2cab-4b6a-987c-e5e6ebe4a900",
"서명": "json",
"결과": [
{
"1TP5운영자": "시퀀스",
"~어린이": [
{
"1TP5운영자": "IndexScan",
"index": "idxstate",
"키스페이스": "맥주 샘플",
"네임스페이스": "기본값",
"스팬": [
{
"범위": {
"높음": [
""CA""
],
"포함": 3,
"낮음": [
""CA""
]
}
}
],
"사용": "gsi"
},
{
"1TP5운영자": "병렬",
"~어린이": {
"1TP5운영자": "시퀀스",
"~어린이": [
{
"1TP5운영자": "Fetch",
"키스페이스": "맥주 샘플",
"네임스페이스": "default"
},
{
"1TP5운영자": "필터",
"조건": "((맥주 샘플.상태) = "CA")"
},
{
"1TP5운영자": "초기 프로젝트",
"결과_기간": [
{
"expr": "(맥주 샘플.상태)"
},
{
"expr": "(맥주 샘플.도시)"
}
]
},
{
"1TP5운영자": "최종 프로젝트"
}
]...나머지는 간결성을 위해 생략했습니다.
그런 다음 이 수정된 쿼리를 커버링 인덱스를 사용하도록 변환하려면 어떻게 해야 할까요?
여기 있습니다,
CREATE INDEX idxstatecity ON 맥주 샘플 (주, 도시) GSI 사용
이제 쿼리를 실행해 보겠습니다:
설명 선택 주, 도시
FROM 맥주 샘플 사용 인덱스(idxstatecity)
여기서 state = "ca" ;
빙고! 커버링 인덱스를 사용하는 쿼리가 됩니다.
{
"1TP5운영자": "IndexScan",
"커버": [
"커버((메타(맥주 샘플).id))",
"cover((맥주 샘플.상태))",
"cover((맥주 샘플.도시))"
],
"index": "idxstatecity",
"키스페이스": "맥주 샘플",
"네임스페이스": "기본값",
"스팬": [
{
"범위": {
"높음": [
"successor("CA")"
],
"포함": 1,
"낮음": [
""CA""
]
}
}
],
"사용": "gsi"
},
표현식 및 집계
표현식 및 집계가 포함된 쿼리는 인덱스 커버링의 이점도 누릴 수 있습니다.
CREATE INDEX idxstatecountry ON 맥주 샘플(주, 국가) GSI 사용
SELECT 국가, 최대(state)
FROM 맥주 샘플 사용 인덱스(idxstatecountry)
여기서 상태는 '%'와 같습니다.
국가별 그룹
결합/교차/제외
인덱스 커버링에도 지원됩니다.
국가 선택
FROM 맥주 샘플
여기서 state = 'ca'
모두 통합
국가 선택
FROM beer-sample`
WHERE STATE = '텍사스'
그리고 인덱스가 이미 정렬되어 있기 때문에 커버링 인덱스의 경우 ORDER BY를 사용하면 쿼리 엔진이 이미 정렬된 인덱스를 사용할 수 있다는 추가적인 이점이 있습니다.
저희의 문서 를 참조하여 자세한 정보와 인덱스 커버링이 유용한 더 많은 시나리오를 확인하세요.
4.1 개발자 미리 보기에서 이 기능을 사용해 보시고 소중한 피드백.
개발자 프리뷰를 사용하여 N1QL을 사용해 볼 수도 있습니다. 쿼리 워크벤치를 사용하여 N1QL 쿼리를 작성하고 실행할 수 있는 멋진 GUI를 제공합니다.