IT

날짜별로 DynamoDB 쿼리

lottoking 2020. 9. 25. 08:20

날짜별로 DynamoDB 쿼리


관계형 데이터베이스 배경에서 왔으며 Amazon의 DynamoDB로 작업합니다.

해시 키 "DataID"와 범위 "CreatedAt"및 그 안에 많은 항목이있는 테이블이 있습니다.

특정 날짜 이후에 생성되고 날짜별로 정렬 된 모든 항목을 가져옵니다. 관계형 데이터베이스에서는 매우 간단합니다.

DynamoDB에서 내가 사용하는 가장 가까운 필터보다 큰 범위 키를 사용하는 쿼리입니다. 유일한 문제는 쿼리를 수행하려는 목적을 무효화하는 것입니다.

그래서 내가 뭘 잘못하고 있니? 내 테이블 스키마가 잘못 되었습니까? 해시 키가 고유하지 고유하지? 아니면 다른 쿼리 방법이 있습니까?


업데이트 된 답변 :

DynamoDB에서는 이러한 종류의 쿼리를 지원하기 위해 위해 보조를 있습니다. 보조 설비는 글로벌 (인덱스가 해시 키에 현존하는 전체 테이블에 있음을 의미 함) 또는 고급가 각 해시 키 파티션 함을 의미하는 쿼리를 만들 때 해시 키도 지정되어야 함을 의미합니다.

이 질문의 사용 사례의 경우 "CreatedAt"필드에 글로벌 보조 강화를 사용합니다.

DynamoDB 보조 보안에 대한 자세한 내용은 보조 계획 문서를 참조하십시오.

원래 답변 :

DynamoDB는 범위 키에서만 인덱싱 된 조회를 허용하지 않습니다. 해시 키는 서비스가 데이터를 찾기 위해 조사 할 파티션을 알 수 있습니다.

물론 스캔 작업을 수행하여 날짜 값으로 필터링 할 수 있습니다.

여러 기본 키에서 시간별로 인덱싱 된 레코드 조회를 수행해야하는 경우 DynamoDB가 사용 관계 서비스가 아니거나 항목을 저장하기 위해 별도의 테이블 (DynamoDB 또는 DynamoDB 또는 스토어)을 활용해야합니다. 인덱싱 된 조회를 수행 할 수있는 메타 데이터입니다.


현재 테이블 구조가 주어지면 현재 DynamoDB에서는 불가능합니다. 큰 도전은 테이블 (파티션)의 해시 키가 별도의 테이블을 만드는 취급한다는 것을 이해하는 것입니다. 어떤면에서 이건 정말 강력합니다 (파티션 키를 사용자 또는 고객의 새 테이블을 만드는 생각하십시오).

쿼리는 단일 파티션에서 수행 할 수 있습니다. 그것이 가족이 이야기의 끝입니다. 즉, 날짜별로 쿼리하려는 경우 (epoch 이후 msec를 사용하려는 경우) 단일 쿼리에서 검색하려는 모든 항목은 동일한 해시 (파티션 키)를 가져옵니다.

자격을 갖추어야합니다. scan찾고있는 기준에 따라 절대적으로 할 수 있습니다. 해당하는 날짜가 있는지 확인합니다. 특히 처음에 날짜별로 이벤트를 저장하는 경우 (즉, 많은 행이있는 경우) 매우 비쌉니다.

문제를 해결하기 위해 모든 데이터를 단일 파티션에 배치하고 싶을 수 있고, 각 파티션이 총 세트 양의 일부만 수신 처리량이 매우 낮습니다.

가장 좋은 방법은 데이터를 저장하기 위해 만들 더 유용한 파티션을 결정하는 것입니다.

  • 모든 행을보아야할까요? 아니면 특정 사용자의 행만보아야?

  • 먼저 월별로 목록을 좁히고 여러 쿼리 (매월 하나씩)를 수행해도 목록을 아니면 연도 별?

  • 시계열 분석을 수행하는 경우 몇 가지 옵션이 있습니다 PUT. query더 쉽게 하기 위해 파티션 키를 계산하고 변경 하거나 추가 전용 로깅에 더 많은 키 네시 스와 같은 다른 aws 제품을 사용합니다.


해시 키 (기본 정렬)는 고유 한 것과 같은 범위가없는 경우는 고유해야합니다.

귀하의 경우에는 비용이 청구될 것입니다.

|  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에도 익숙합니다) 생산성을 높이는 가장 빠른 방법입니다. 스키마와 관련하여 제약이 없기 때문에 작동하는 것을 채울 수 있으며 가장 효율적인 방식으로 작업 할 수있는 대역폭이 확보되면 상황을 바꿀 수 있습니다.


이 문제를 해결하기 위해 제가 따랐던 접근 방식은 아래와 같이 Global Secondary Index를 생성하는 것입니다. 이것이 최선의 접근 방식인지 확실하지 않지만 누군가에게 유용 할 수 있기를 바랍니다.

Hash Key                 | Range Key
------------------------------------
Date value of CreatedAt  | CreatedAt

HTTP API 사용자에게 데이터를 검색 할 일 수를 지정하는 제한이 적용되며 기본값은 24 시간입니다.

이렇게하면 항상 HashKey를 현재 날짜로 지정할 수 있으며 RangeKey는 검색하는 동안> 및 <연산자를 사용할 수 있습니다. 이렇게하면 데이터가 여러 샤드에 분산됩니다.


'제품 카테고리'ID 라인을 따라 해시 키를 만든 다음 끝에 고유 ID가 추가 된 타임 스탬프의 조합으로 범위 키를 만들 수 있습니다. 이렇게하면 해시 키를 알 수 있고보다 큼 날짜를 쿼리 할 수 ​​있습니다.


동일한 해시 키를 여러 개 가질 수 있습니다. 하지만 다양한 범위 키가있는 경우에만 가능합니다. 파일 형식이라고 생각하면됩니다. 형식이 다른 한 동일한 폴더에 동일한 이름을 가진 2 개의 파일을 가질 수 있습니다. 형식이 같으면 이름이 달라야합니다. 동일한 개념이 DynamoDB의 해시 / 범위 키에 적용됩니다. 해시를 이름으로, 범위를 형식으로 생각하면됩니다.

Also, I don't recall if they had these at the time of the OP (I don't believe they did), but they now offer Local Secondary Indexes.

My understanding of these is that it should now allow you to perform the desired queries without having to do a full scan. The downside is that these indexes have to be specified at table creation, and also (I believe) cannot be blank when creating an item. In addition, they require additional throughput (though typically not as much as a scan) and storage, so it's not a perfect solution, but a viable alternative, for some.

그래도 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로 제한됩니다.

참고 URL : https://stackoverflow.com/questions/14836600/querying-dynamodb-by-date