관계형 데이터베이스 배경에서 왔으며 Amazon의 DynamoDB로 작업하려고합니다.
해시 키 “DataID”와 범위 “CreatedAt”및 그 안에 많은 항목이있는 테이블이 있습니다.
특정 날짜 이후에 생성되고 날짜별로 정렬 된 모든 항목을 가져 오려고합니다. 관계형 데이터베이스에서는 매우 간단합니다.
DynamoDB에서 내가 찾을 수있는 가장 가까운 것은 필터보다 큰 범위 키를 사용하는 쿼리입니다. 유일한 문제는 쿼리를 수행하려면 목적을 무효화하는 해시 키가 필요하다는 것입니다.
그래서 내가 뭘 잘못하고 있니? 내 테이블 스키마가 잘못 되었습니까? 해시 키가 고유하지 않아야합니까? 아니면 다른 쿼리 방법이 있습니까?
답변
업데이트 된 답변 :
DynamoDB에서는 이러한 종류의 쿼리를 지원하기 위해 보조 인덱스를 지정할 수 있습니다. 보조 인덱스는 글로벌 (인덱스가 해시 키에 걸쳐 전체 테이블에 걸쳐 있음을 의미 함)이거나 인덱스가 각 해시 키 파티션 내에 존재 함을 의미하므로 쿼리를 만들 때 해시 키도 지정되어야 함을 의미합니다.
이 질문의 사용 사례의 경우 “CreatedAt”필드에 글로벌 보조 인덱스를 사용하려고합니다.
DynamoDB 보조 인덱스에 대한 자세한 내용은 보조 인덱스 문서를 참조하십시오.
원래 답변 :
DynamoDB는 범위 키에서만 인덱싱 된 조회를 허용하지 않습니다. 해시 키는 서비스가 데이터를 찾기 위해 조사 할 파티션을 알 수 있도록 필요합니다.
물론 스캔 작업을 수행하여 날짜 값으로 필터링 할 수 있지만 전체 테이블 스캔이 필요하므로 이상적이지 않습니다.
여러 기본 키에서 시간별로 인덱싱 된 레코드 조회를 수행해야하는 경우 DynamoDB가 사용하기에 이상적인 서비스가 아니거나 항목을 저장하기 위해 별도의 테이블 (DynamoDB 또는 관계형 스토어)을 활용해야 할 수 있습니다. 인덱싱 된 조회를 수행 할 수있는 메타 데이터입니다.
답변
현재 테이블 구조가 주어지면 현재 DynamoDB에서는 불가능합니다. 큰 도전은 테이블 (파티션)의 해시 키가 별도의 테이블을 만드는 것으로 취급되어야한다는 것을 이해하는 것입니다. 어떤면에서 이것은 정말 강력합니다 (파티션 키를 각 사용자 또는 고객 등에 대한 새 테이블을 만드는 것으로 생각하십시오).
쿼리는 단일 파티션에서만 수행 할 수 있습니다. 그것이 정말로 이야기의 끝입니다. 즉, 날짜별로 쿼리하려는 경우 (epoch 이후 msec를 사용하려는 경우) 단일 쿼리에서 검색하려는 모든 항목은 동일한 해시 (파티션 키)를 가져야합니다.
자격을 갖추어야합니다. scan
찾고있는 기준에 따라 절대적으로 할 수 있습니다. 문제는 없지만 테이블의 모든 행을 살펴보고 해당 행에 매개 변수와 일치하는 날짜가 있는지 확인하게됩니다. 특히 처음에 날짜별로 이벤트를 저장하는 경우 (즉, 많은 행이있는 경우) 매우 비쌉니다.
문제를 해결하기 위해 모든 데이터를 단일 파티션에 저장하고 싶을 수 있지만, 각 파티션이 총 세트 양의 일부만 수신하므로 처리량이 매우 낮습니다.
가장 좋은 방법은 데이터를 저장하기 위해 만들 더 유용한 파티션을 결정하는 것입니다.
-
정말로 모든 행을보아야합니까? 아니면 특정 사용자의 행만보아야합니까?
-
먼저 월별로 목록을 좁히고 여러 쿼리 (매월 하나씩)를 수행해도됩니까? 아니면 연도 별?
-
시계열 분석을 수행하는 경우 몇 가지 옵션이 있습니다
PUT
.query
더 쉽게 하기 위해 파티션 키를 계산 된 것으로 변경 하거나 추가 전용 로깅에 적합한 kinesis와 같은 다른 aws 제품을 사용하십시오.
답변
이 문제를 해결하기 위해 제가 따랐던 접근 방식은 아래와 같이 Global Secondary Index를 생성하는 것입니다. 이것이 최선의 접근 방식인지 확실하지 않지만 누군가에게 유용하다면 희망을 갖고 있습니다.
Hash Key | Range Key
------------------------------------
Date value of CreatedAt | CreatedAt
HTTP API 사용자에게 데이터 검색 일 수를 지정하는 제한이 적용되며 기본값은 24 시간입니다.
이렇게하면 항상 HashKey를 현재 날짜로 지정할 수 있으며 RangeKey는 검색하는 동안> 및 <연산자를 사용할 수 있습니다. 이렇게하면 데이터가 여러 샤드에 분산됩니다.
답변
해시 키 (기본 정렬)는 고유해야합니다 (다른 사람이 언급 한 것과 같은 범위가없는 경우).
귀하의 경우 테이블을 쿼리하려면 보조 인덱스가 있어야합니다.
| ID | DataID | Created | Data |
|------+--------+---------+------|
| hash | xxxxx | 1234567 | blah |
해시 키는 ID입니다. 보조 인덱스는 다음과 같이 정의됩니다. DataID-Created-index (DynamoDB에서 사용할 이름)
그런 다음 다음과 같은 쿼리를 만들 수 있습니다.
var params = {
TableName: "Table",
IndexName: "DataID-Created-index",
KeyConditionExpression: "DataID = :v_ID AND Created > :v_created",
ExpressionAttributeValues: {":v_ID": {S: "some_id"},
":v_created": {N: "timestamp"}
},
ProjectionExpression: "ID, DataID, Created, Data"
};
ddb.query(params, function(err, data) {
if (err)
console.log(err);
else {
data.Items.sort(function(a, b) {
return parseFloat(a.Created.N) - parseFloat(b.Created.N);
});
// More code here
}
});
기본적으로 쿼리는 다음과 같습니다.
SELECT * FROM TABLE WHERE DataID = "some_id" AND Created > timestamp;
보조 인덱스는 필요한 읽기 / 쓰기 용량 단위를 증가 시키므로이를 고려해야합니다. 읽기와 시간에 비용이 많이 드는 스캔을 수행하는 것보다 훨씬 낫습니다 (내가 믿는 100 개 항목으로 제한됨).
이것이 최선의 방법은 아니지만 RD에 익숙한 사람에게는 (저는 SQL에도 익숙합니다) 생산성을 얻는 가장 빠른 방법입니다. 스키마와 관련하여 제약이 없기 때문에 작동하는 것을 채울 수 있으며 가장 효율적인 방식으로 작업 할 수있는 대역폭이 있으면 상황을 변경할 수 있습니다.
답변
‘제품 카테고리’ID의 줄을 따라 해시 키를 만든 다음 끝에 고유 ID가 추가 된 타임 스탬프의 조합으로 범위 키를 만들 수 있습니다. 이렇게하면 해시 키를 알 수 있고보다 큼 날짜를 쿼리 할 수 있습니다.
답변
동일한 해시 키를 여러 개 가질 수 있습니다. 하지만 다양한 범위 키가있는 경우에만. 파일 형식이라고 생각하면됩니다. 형식이 다른 한 동일한 폴더에 동일한 이름을 가진 2 개의 파일을 가질 수 있습니다. 형식이 같으면 이름이 달라야합니다. 동일한 개념이 DynamoDB의 해시 / 범위 키에 적용됩니다. 해시를 이름으로, 범위를 형식으로 생각하면됩니다.
또한 OP 당시에 이러한 항목이 있었는지 기억하지 못하지만 (그렇지 않다고 생각합니다) 이제는 Local Secondary Index를 제공합니다.
이것에 대한 나의 이해는 이제 전체 스캔을 수행하지 않고도 원하는 쿼리를 수행 할 수 있어야한다는 것입니다. 단점은 테이블 생성시 이러한 인덱스를 지정해야하고 항목을 생성 할 때 비워 둘 수 없다는 것입니다. 또한 추가 처리량 (일반적으로 스캔만큼 많지는 않지만)과 스토리지가 필요하므로 완벽한 솔루션은 아니지만 일부에게는 실행 가능한 대안입니다.
그래도 DynamoDB를 사용하는 기본 방법으로 Mike Brant의 답변을 권장합니다. 그 방법을 직접 사용하십시오. 제 경우에는 ID로 해시 키만있는 중앙 테이블이 있고 쿼리 할 수있는 해시 및 범위가있는 보조 테이블이있는 경우 항목이 코드를 중앙 테이블의 “관심 항목”으로 직접 가리 킵니다. .
보조 인덱스에 대한 추가 데이터는 여기 Amazon의 DynamoDB 설명서에서 찾을 수 있습니다. 에있는 .
어쨌든,이 스레드에서 발생하는 다른 모든 사람에게 도움이되기를 바랍니다.
답변
업데이트 된 답변
처리량을 예측할 수있는 Dynamo DB 쿼리를 사용하여이 작업을 수행하는 편리한 방법은 없습니다. 한 가지 (하위 최적) 옵션은 인공 HashKey 및 CreatedAt과 함께 GSI를 사용하는 것입니다. 그런 다음 HashKey만으로 쿼리하고 ScanIndexForward를 언급하여 결과를 정렬합니다. 자연적인 HashKey (항목의 카테고리 등)를 생각 해낼 수 있다면이 방법이 승자입니다. 반면에 모든 항목에 대해 동일한 HashKey를 유지하면 데이터 세트가 10GB (하나의 파티션)를 초과 할 때 처리량에 영향을 미칩니다.
원래 답변 :
이제 GSI를 사용하여 DynamoDB에서이 작업을 수행 할 수 있습니다. “CreatedAt”필드를 GSI로 만들고 (GT some_date)와 같은 쿼리를 실행합니다. 이러한 종류의 쿼리에 대해 날짜를 숫자 (epoch 이후 밀리 초)로 저장합니다.
자세한 내용은 여기에서 확인할 수 있습니다. 글로벌 보조 인덱스-Amazon DynamoDB : http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.
이것은 매우 강력한 기능입니다. 쿼리는 (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) 조건-Amazon DynamoDB : http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html로 제한됩니다.