DynamoDB 필터링 전략
DynamoDB의 "필터링"은 동일한 단어를 사용하는 네 가지 다른 것을 의미합니다. 세
데이터를 읽고 청구하기 전에 데이터 범위를 좁힙니다. 하나 - 이름이 Filter인 것 -
후 범위를 좁힙니다. 어느 것이 가장 뛰어난 기술인지 아는 것.
DynamoDB에서 필터링은 어떻게 작동합니까?
DynamoDB에는 4가지 필터링 방법이 있으며, 요금이 청구된 후에는 하나만 실행됩니다. 는 파티션을 선택하고, 정렬 키는 슬라이스를 좁히고, 희소 인덱스는 속성 존재 여부에 따라 필터링합니다. 세 가지 모두 측정 전 읽기 비용을 절감합니다. FilterExpression은 읽기 후에 실행되므로 응답이 줄어들지만 청구서는 줄어들지 않습니다.
- 은 가장 저렴한 필터입니다. 파티션을 선택하므로 절대 테이블의 나머지 부분을 터치하세요.
- 필터 내부
begins_with,between,<,>— 아직 청구 전이며 여전히 저렴합니다. - 부재로 필터링: 항목이 있는 경우에만 색인에 나타납니다. 인덱스 속성이 있으므로 인덱스는 필터링된 집합입니다.
FilterExpression은 트랩입니다. DynamoDB가 읽기를 측정한 후에 실행되므로 응답 크기는 줄어들지만 청구서는 결코 줄어들지 않습니다.
예제 설정
제품 카탈로그입니다. 테이블 1개, 파티션 키 PK, 정렬 키 SK:
PK = "DEPT#kitchen" SK = "PROD#00194"
모든 제품에는 price, inStock(부울) 및 clearanceAt도 포함됩니다.
(유닉스 타임스탬프, 정리 표시가 있는 항목에만 표시됨) 항목
부서는 제품 ID별로 정렬된 파티션을 공유합니다.
우리는 네 가지 액세스 패턴을 원합니다. 각각은 서로 다른 필터링 전략에 매핑됩니다. 그리고 그 중 하나라도 잘못된 선택을 하면 영원히 대가를 치르게 될 것입니다.
파티션 키로 필터링
"kitchen에 있는 모든 물건을 주세요." 파티션 키는 이에 대해 직접적으로 응답합니다.
Query PK = "DEPT#kitchen"
DynamoDB는 정확히 하나의 파티션을 읽습니다. 테이블의 다른 어떤 것도 건드리지 않거나 청구됨. 이것은 중요한 의미에서 무료인 유일한 필터입니다. 0 and 1의 차이.
SQL에서 보면 거꾸로 된 느낌입니다. WHERE department = 'kitchen'가 없습니다.
인덱스를 스캔할 때는 _파티션 이름을 지정_하면 됩니다. 이름을 밝힐 수 없다면, 그것은
쿼리 문제가 아니라 모델링 문제입니다.
정렬 키로 필터링
"PROD#00100 이상의 주방용품을 주세요." 정렬 키가 inside 범위를 좁힙니다.
파티션에 저장되며 읽기가 측정되기 전에 수행됩니다.
Query PK = "DEPT#kitchen" AND SK between "PROD#00100" AND "PROD#00200"
정렬 키 조건은 의도적으로 제한됩니다: =, <, <=, >, >=,
between, 및 begins_with. OR도 없고 임의의 술어도 없습니다.
이러한 제약은 읽기 대상을 유지하는 것입니다. DynamoDB는 연속적인 경로를 따라 이동합니다. 전체 파티션이 아닌 슬라이스.
여기서 중요한 것은 정렬 키를 인코딩하는 방법입니다. 귀하의 패턴이 "가격 기준"인 경우
band", PROD#<id> 정렬 키는 도움이 되지 않습니다. 키에 가격을 입력하게 됩니다.
그것은 sort-key strategy 결정입니다. 쿼리 타임이 아닌 디자인 타임에.
희소 인덱스로 필터링
"현재 허가된 모든 것을 나에게 주십시오." 대부분의 제품은 그렇지 않으므로 귀하도 그렇지 않습니다. 카탈로그를 읽고 그 중 몇 가지를 찾고 싶습니다.
희소 색인은 부재로 인해 이 문제를 해결합니다. A 만 해당 해당 항목에 인덱스의 키 속성이 두 가지 모두 있는 경우 해당 항목을 포함합니다.
GSI 파티션 키로 상수 clearance = "CLEARANCE" 플래그 설정 —
통관 품목에만 기록됩니다. 정렬 키는 clearanceAt이고,
인덱스에는 다른 것이 없습니다.
AWS에서는 다음과 같이 설명합니다. 글로벌 보조 인덱스에는 다음 항목만 포함됩니다. 인덱스의 키 속성이므로 키 속성이 누락된 항목은 단순히 전파됩니다([AWS — 희소 인덱스 활용][sparse]).
이제 쿼리는 통관 품목만 읽고 해당 품목에 대해서만 청구됩니다.
Query ON ClearanceIndex GSI_PK = "CLEARANCE" (sorted by clearanceAt)
데이터를 썼을 때 필터가 발생했습니다. — 설정 여부를 선택하여
전혀 clearanceAt. 인덱스는 필터링된 집합입니다. 참조
GSI vs LSI에는 인덱스 유형이 적합합니다.
FilterExpression을 사용한 필터
"재고 있는 주방용품 주세요." inStock은 핵심 속성이 아닙니다.
그래서 당신은 FilterExpression에 도달합니다:
Query PK = "DEPT#kitchen"
Filter inStock = true
DynamoDB는 kitchen 파티션의 모든 항목을 읽고 해당 항목의 용량을 측정합니다.
그리고 그런 다음 품절된 제품은 삭제합니다.
공식 규칙: 필터 표현식은 "1Query이 끝난 후에 적용되지만,
결과가 반환되기 전에" 및 "쿼리는 동일한 양의 읽기를 소비합니다.
필터 표현식의 존재 여부에 관계없이 용량" — 이미
전체 읽기에 대한 비용이 지불됩니다(AWS — 쿼리에 대한 필터 표현식).
따라서 kitchen에 10,000개의 제품이 있고 12개의 재고가 있는 경우 10,000개를 읽으려면 비용을 지불해야 합니다.
반응이 작습니다. 청구서는 그렇지 않습니다. FilterExpression은 페이로드를 축소합니다.
전선을 건너면 절대 읽히지 않습니다.
두 번째로 더 날카로운 모서리가 있습니다. 페이지 매김은 필터링 전에 측정됩니다. 페이지 1MB의 일치 항목이 아니라 1MB의 읽기 항목입니다.
필터는 LastEvaluatedKey 세트가 포함된 빈 페이지를 반환할 수 있습니다. — DynamoDB는
전체 메가바이트, 일치하는 항목이 없어 빈 배열을 건네주었습니다. 계속 페이징을 하고,
빈 페이지마다 비용을 지불했습니다.
다음을 사용하여 이름, 값, 올바른 예약어 이스케이프 등 표현식을 작성합니다.
DynamoDB Expression Builder 그래서
#inStock/:val 자리 표시자는 첫 번째 시도에서 정확했습니다.
아래 빌더는 FilterExpression와 함께 Scan로 사전 설정되어 있습니다. — 정확한
위의 안티 패턴. 필터는 키 조각이 아닌 전체 테이블에서 실행됩니다.
4개를 비교해보세요
| 필터링할 때 | 읽기 비용이 절감되나요? | 술어 전력 | 설치 비용 | |
|---|---|---|---|---|
| 파티션 키 | 읽기 전에 | 예 — 하나의 파티션 | 평등만 | 무료(핵심) |
| 정렬 키 | 읽기 전에 | 예 — 슬라이스 | 범위 / begins_with | 정렬 키 디자인 |
| 희소 인덱스 | 읽기 전에 | 예 - 인덱스 전용 | 속성의 존재 | 추가 GSI + 쓰기 비용 |
| 필터 표현식 | 읽은 후 | 아니요 | 거의 모든 조건 | 없음 |
표를 위에서 아래로 읽으십시오. 술어의 힘은 up, 비용 통제는 증가합니다.
아래로. FilterExpression은 다음과 같이 실행되기 때문에 무엇이든 정확하게 표현할 수 있습니다.
이미 읽은 항목 — 이는 돈을 절약할 수 없는 것과 같은 이유입니다.
DynoTable에서 보기
필터를 사용하여 Query를 실행하면 읽은 항목과 항목 사이의 간격이
_returned_가 전체 이야기입니다. DynoTable은 항목 옆에 스캔된 항목을 표시합니다.
필터링된 읽기 스트림으로 반환됩니다. 따라서 전체 파티션을 조용히 읽는 필터가 표시됩니다.
월별 청구서에 숨어 있습니다.
실제 교차 항목 질문의 경우 필터가 답변할 수 없습니다. — "평균 가격
부서", "재고가 있는 제품이 리뷰에 추가되었습니다" — DynoTable의 SQL
Workbench는 GROUP BY, JOIN로 실행되며 제한된 범위에 걸쳐 클라이언트 측을 집계합니다.
결과 집합을 테이블 전체 Scan로 컴파일하는 대신.
함정과 다음 단계
- 기본 액세스 경로로
FilterExpression을 사용하지 마십시오. 패턴이 다음과 같은 경우 일반적인 경우 키 또는 희소 인덱스로 모델링합니다. 필터는 마지막 작은 것입니다 약간 좁아지지만 대부분은 아닙니다. - 빈 페이지를 확인하세요. 필터링된 쿼리로 인해 오랜 시간 동안 페이지가 반환될 수 있습니다.
아무것도. 명예
LastEvaluatedKey; 빈 페이지가 "완료"를 의미한다고 가정하지 마십시오. - 희소 인덱스는 무료가 아닙니다. 모든 작업에 대해 쓰기 용량과 저장 공간이 필요합니다. 그 안에 들어 있는 아이템 — 속성이 희귀할 때는 저렴하고, 그렇지 않을 때는 가격이 저렴합니다.
필터링된 읽기에 실제로 드는 비용을 추정합니다. pricing calculator, 그리고 try DynoTable에서 반환된 행에 대해 소비된 용량을 확인합니다. 나만의 테이블.