본문 바로가기
Web/AWS

[ DynamoDB ] Geohash 알맞은 hashkey 구하기

by 기저귀찬개발자 2020. 6. 15.

간략 설명

Geohash = Geohash에서는 위도와 경도를 가지고 Location마다 고유의 hash값이 붙게 되고 근접한 위치일수록 hash값의 접두사 부분이 비슷해진다. (https://en.wikipedia.org/wiki/Geohash )

 

Dynamodb-geo = DynamoDB에 Geohash 지리 데이터의 생성, 수정, 삭제, 근접 데이터 등의 함수를 지원해주는 package

(https://www.npmjs.com/package/dynamodb-geo)

 

DynamoDB와 hashKey와의 관계 

Geohash는 위도와 경도를 가지고 Location마다 고유의 hash값이 붙게 되는데 hashKey가 partition key로 구성되어 길이에 따라 검색 성능이 좌우된다. 

hashKey값이 길어질수록 partition이 분산시킬 수 있지만 반경에 커질수록 접근횟수가 더욱 많아진다.

hashKey값이 작아들수록 partition이 적어지지만 한꺼번에 많은 데이터를 읽어야 할 가능성도 커지므로 높은 RCU값을 요구할 수 있다.

 

글 목적

Dynamodb에 들어가는 데이터 구조에서 partition-key에 해당하는 hashKey의 최적의 길이 구하기

기본값은 6으로 설정되어 있는데 다른 길이를 사용할 경우 어떤 차이가 있을지 궁금해서 테스트를 해보았다.

 

테이블 구조

{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "hashKey",
                "AttributeType": "N"
            },
            {
                "AttributeName": "rangeKey",
                "AttributeType": "S"
            },
            {
                "AttributeName": "geohash",
                "AttributeType": "N"
            }
        ],
        "TableName": "footprint-key10",
        "KeySchema": [
            {
                "AttributeName": "hashKey",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "rangeKey",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": 1591854620.423,
        "ProvisionedThroughput": {
            "LastIncreaseDateTime": 0.0,
            "LastDecreaseDateTime": 0.0,
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 10,
            "WriteCapacityUnits": 5
        },
        "TableSizeBytes": 84517270,
        "ItemCount": 28921,
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/footprint-key10",
        "LocalSecondaryIndexes": [
            {
                "IndexName": "geohash-index",
                "KeySchema": [
                    {
                        "AttributeName": "hashKey",
                        "KeyType": "HASH"
                    },
                    {
                        "AttributeName": "geohash",
                        "KeyType": "RANGE"
                    }
                ],
                "Projection": {
                    "ProjectionType": "ALL"
                },
                "IndexSizeBytes": 84517270,
                "ItemCount": 28921,
                "IndexArn": "arn:aws:dynamodb:ddblocal:000000000000:table/footprint-key10/index/geohash-index"
            }
        ]
    }
}

 

 

데이터 example

PMNTN_LT: { N: '0.29' },
PMNTN_GODN: { N: '4' },
rangeKey: { S: '113200102-13006' },
MNTN_CODE: { N: '113200102' },
hashKey: { N: '385416510' },
PMNTN_SN: { S: '13006' },
geoJson:
{ S:
'{"type":"POINT","coordinates":[127.02323388792045,37.66574049674894]}' },
PMNTN_UPPL: { N: '5' },
geohash: { N: '3854165107149761647' },
PMNTN_DFFL: { S: '쉬움' },
MNTN_NM: { S: '도봉산_자운봉' },
COORDINATES:
{ S:
'127.0220417676135,37.6649956621689,127.02236143526451,37.66508030050781,127.02290151424471,37.665459907141816,127.02323388792045,37.66574049674894,127.02350399697669,37.66613666211782,127.02375334541375,37.66654934059262,127.02412730644566,37.666961992186216' } } 

 

테스트 nodejs source

const ddbGeo = require('dynamodb-geo');
const AWS = require('aws-sdk');

// Set up AWS
AWS.config.update({
    accessKeyId: '-',
    secretAccessKey: '-',
    region: 'ap-northeast-2',
    endpoint: new AWS.Endpoint('http://localhost:8000')
});

const ddb = new AWS.DynamoDB();
const config = new ddbGeo.GeoDataManagerConfiguration(ddb, 'footprint-key9');
config.hashKeyLength = 9;
const footprintManager = new ddbGeo.GeoDataManager(config);

console.time("check1");
       footprintManager.queryRadius({
         RadiusInMeter: 10000,
         CenterPoint: {
           latitude: 37.6584085,
           longitude: 127.02928809999999
         }
       }).then(function(data){
         console.log(data);
         console.timeEnd("check1");

       });
return;

 

 

 

아래는 각각 3만건 정도의 아이템이 들어있는 테이블을 hashKey 길이와 검색 반경을 다르게 해서 테스트 해본 결과이다.

 

반경 1km

차수|Key 10 9 8 7 6 5
1차 10031.209ms 721.379ms 1006.917ms 1370.448ms 942.796ms 922.263ms
2차 3069.371ms 975.226ms 388.750ms 436.482ms 396.267ms 601.796ms
3차 2858.357ms 944.124ms 431.603ms 410.343ms 394.425ms 385.747ms
4차 3084.536ms 1316.677ms 392.813ms 463.363ms 382.464ms 404.064ms
5차 3364.704ms 882.385ms 403.927ms 400.618ms 403.406ms 376.223ms
평균 4481ms 967ms 524ms 615ms 437ms 531ms

 

반경 10km - key10은 error때문에 진행하지 않았다.

차수|Key 10 9 8 7 6 5
1차 - 37188.304ms 7158.762ms 5251.057ms 7551.026ms 7401.075ms
2차 - 33725.597ms 5677.798ms 3791.047ms 4254.680ms 3741.121ms
3차 - 30395.661ms 4929.117ms 3829.746ms 3752.136ms 3782.613ms
4차 - 27362.903ms 4971.104ms 3958.846ms 3621.315ms 3665.493ms
5차 - 37190.278ms 4939.326ms 3792.199ms 3632.907ms 3712.111ms
평균   33172ms 5534ms 4124ms 4562ms 4460ms

 

반경 100km - key8 이상부터는 error때문에 진행하지 않았다.

차수|Key 10 9 8 7 6 5
1차 - - - 25551.602ms 16646.206ms 15916.730ms
2차 - - - 18529.825ms 11139.500ms 9787.848ms
3차 - - - 17866.582ms 16661.607ms 10249.526ms
4차 - - - 17827.254ms 10570.851ms 9639.297ms
5차 - - - 23478.211ms 9925.086ms 9733.040ms
평균 - - - 20650ms 12988ms 11064ms

 

반경이 100km일때는 길이가 5인게 빠르지만 100km까지는 서비스하지 않을 예정이라 6으로 정했다.

댓글