【问题标题】:Table design in DynamoDBDynamoDB 中的表设计
【发布时间】:2020-08-07 22:36:42
【问题描述】:

我是 NoSQL DB 和无服务器的初学者。我的应用程序有一个名为Trips 的表。表格的参数是{id, route, cost, selling, type, date, LR, asset }和一堆其他不相关的文档编号,其中id是由uuid生成的。

现在我想查询数据库给我

  1. 使用日期参数返回一个日期范围内的所有行程。
  2. 使用日期和资产参数返回给定时间段内资产的所有行程。
  3. 使用日期路线参数返回给定时间段内路线的所有行程。

2 和 3 使用 keyConditionExpression 可以正常工作,但对于 1,我需要在扫描上使用 filterExpression 而不是查询,这可能会使其相对较慢,因为它是在查询完成后执行的。有没有更好的方法来形成架构?

Trips 表中,架构是这样的

 tripTable:
  Type: "AWS::DynamoDB::Table"
  Properties:
    AttributeDefinitions:
      [
        { "AttributeName": "id", "AttributeType": "S" },
        { "AttributeName": "date", "AttributeType": "S" },
        { "AttributeName": "Asset", "AttributeType": "S" },
        { "AttributeName": "Route", "AttributeType": "S" },
      ]

    KeySchema:
      [
        { "AttributeName": "date", "KeyType": "HASH" },
        { "AttributeName": "id", "KeyType": "RANGE" },
      ]
    ProvisionedThroughput:
      ReadCapacityUnits: 5
      WriteCapacityUnits: 5
    StreamSpecification:
      StreamViewType: "NEW_AND_OLD_IMAGES"
    TableName: ${self:provider.environment.TRIPS}
    GlobalSecondaryIndexes:
      - IndexName: TripsVSAssets
        KeySchema:
          - AttributeName: asset
            KeyType: HASH
          - AttributeName: date
            KeyType: RANGE
        Projection:
          ProjectionType: ALL
        ProvisionedThroughput:
          ReadCapacityUnits: "5"
          WriteCapacityUnits: "5"
        GlobalSecondaryIndexes:
      - IndexName: RoutesVSAssets
        KeySchema:
          - AttributeName: route
            KeyType: HASH
          - AttributeName: date
            KeyType: RANGE
        Projection:
          ProjectionType: ALL
        ProvisionedThroughput:
          ReadCapacityUnits: "5"
          WriteCapacityUnits: "5"

【问题讨论】:

    标签: node.js database-design nosql amazon-dynamodb serverless


    【解决方案1】:

    您还需要一个索引列,其中分区键(哈希类型)将是一个随机数,比如说从 0 到 20。排序键(范围类型),再次放在那里。

    所以要查询特定时间之间的所有行程,需要并行查询20次,partition Key作为0到20之间的每个数字,Sort Key作为时间范围。

    https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-modeling-nosql-B.html

    查看上述指南,转到页面末尾的表格并查看第 5 个条目

    如果您在此处进行扫描,那么 dynamoDB 会按每个分区键向您收费。在上述并行查询技术中,您只需为 N 次查询(上述情况下为 20 次)付费。

    【讨论】:

    • 并行扫描 20 次,当数据库增长时,这不是需要很长时间吗?
    • @Summet 我尝试了您的方法,但响应中的一个对象不按顺序排列。在 promise.all 为所有 20 个 promise 解决后,我需要做些什么吗?
    • @DivyeShah 随着数据库的增长,运行 20 次查询(不是扫描)不会花费很长时间,因为这就是 DynamoDB 提供的。但是,如果您的查询响应数据大小增加到 400kb,您可能会注意到差异,然后是的,您需要合并所有 20 个响应的响应并在应用程序级别对其进行排序。
    【解决方案2】:

    我最近遇到了类似的问题,并选择使用year 作为分区键和日期作为排序键。这适合我的数据量,让我按日期查询,并且大多数情况下只运行一个查询。如果您有大量数据,也许month 甚至week 会更合适(或完全不同)。

    然后,通过我的方法,我只需要检查我想要查看的日期范围是否跨越两年,在这种情况下(即非常罕见),Lambda 会进行两个查询并组合结果。我在下面包含了一些草稿代码,以防它有用(可能有更好的方法,但这对我有用!)我还建议快速阅读:https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/

    module.exports.getLatest = async event => {
    
      // some date and formatting code here not included
    
      var params1 = {
        ExpressionAttributeNames: { "#date": "date", "#year": "year" },
        ExpressionAttributeValues: {
          ':d': isoDate,
          ':y1': y1
         },
       KeyConditionExpression: '#year = :y1 AND #date > :d',
       TableName: process.env.HEADLINES_TABLE
      }
    
      if (y1 != y2) {
       // define var params2 (the same as params1 except it uses y2)
      }
    
      try {
        let result;
    
        // if the date range cuts across partitions (years), fire off two queries and wait for both
    
        if(y1 != y2) {
            let resultPromise1 = client.query(params1).promise();
            let resultPromise2 = client.query(params2).promise();
            const [result1, result2] = await Promise.all([resultPromise1,resultPromise2]);
            result = [...result1.Items, ...result2.Items];
        } else { 
            result = await client.query(params1).promise();
        }
    
        return {
          // stringify and return result.Items, statuscode 200 etc.
        }
      }
      // catch {} code here (irrelevant for the answer)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-10
      • 1970-01-01
      • 1970-01-01
      • 2012-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      相关资源
      最近更新 更多