简体   繁体   English

单表设计 - DynamoDB - 将两个表合并为一个?

[英]Single Table Design - DynamoDB - Merge two tables into one?

I've watched this video and I was thinking about the Single Table Design.我看过这个视频,我在考虑单表设计。 Is it a good idea to merge these two tables into one, just like the example in the video?像视频中的示例一样,将这两个表合并为一个是个好主意吗? Since they are related to each other (user trades and user transfers ie deposits and withdrawals) and the access patterns are all about given an exchange name and an account name.由于它们彼此相关(用户交易和用户转账,即存款和取款)并且访问模式都是关于给定交易所名称和帐户名称。

在此处输入图像描述

The access patterns I'm interested in right now:我现在感兴趣的访问模式:

  • Get the last user transfer for a given exchange and an account name.获取给定交易所的最后一次用户转账和账户名。
  • Get all user trades by date range.按日期范围获取所有用户交易。
  • Get all user transfers by date range.按日期范围获取所有用户转移。

Is it a good idea to merge both tables into one with the same PK and SK?将两个表合并为一个具有相同 PK 和 SK 的表是个好主意吗? There will be items with SK TradeDate#12/17/2022 and others with TransferDate#12/17/2022 .将有 SK TradeDate#12/17/2022和其他TransferDate#12/17/2022的项目。

I'm about to figure out how to do the date range queries.我即将弄清楚如何进行日期范围查询。 I would have to use GSIs.我将不得不使用 GSI。

User Trades用户交易

+-------------------------------+----------------------------------------+---------+----------+-----+-------------+------------+-------+-------------+----------+-------------------------------+-----------+-----------------------------------+
|              PK               |                   SK                   | Account | Exchange | Fee | FeeCurrency | Instrument | Price | ProductType | Quantity |           TradeDate           |  TradeId  |             UpdatedAt             |
+-------------------------------+----------------------------------------+---------+----------+-----+-------------+------------+-------+-------------+----------+-------------------------------+-----------+-----------------------------------+
| Exchange#Binance#Account#main | TradeDate#12/17/2022 4:59:12 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:17:56.436+00:00 | 814696766 | 2023-01-26T23:17:57.7786154+00:00 |
| Exchange#Binance#Account#main | TradeDate#12/17/2022 5:38:23 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:06.876+00:00 | 814746356 | 2023-01-26T23:57:08.3696852+00:00 |
| Exchange#FTX#Account#main     | TradeDate#12/17/2021 5:38:23 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:21.226+00:00 | 814746461 | 2023-01-26T23:57:21.8543695+00:00 |
| Exchange#FTX#Account#main     | TradeDate#12/19/2022 4:59:12 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:21.901+00:00 | 814746513 | 2023-01-26T23:57:22.528155+00:00  |
| Exchange#Binance#Account#main | TradeDate#12/17/2022 4:59:12 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:22.348+00:00 | 814746517 | 2023-01-26T23:57:22.9753506+00:00 |
| Exchange#Binance#Account#main | TradeDate#12/17/2022 5:38:23 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:22.802+00:00 | 814746518 | 2023-01-26T23:57:23.429097+00:00  |
| Exchange#FTX#Account#main     | TradeDate#12/17/2021 5:38:23 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:23.252+00:00 | 814746521 | 2023-01-26T23:57:23.8756532+00:00 |
| Exchange#FTX#Account#main     | TradeDate#12/19/2022 4:59:12 PM +02:00 | main    | Binance  |   0 | BNB         | BTCBUSD    |     0 | Spot        |  0.00086 | 2023-01-26T23:57:23.759+00:00 | 814746524 | 2023-01-26T23:57:24.3824745+00:00 |
+-------------------------------+----------------------------------------+---------+----------+-----+-------------+------------+-------+-------------+----------+-------------------------------+-----------+-----------------------------------+

User Transfers (Deposits + Withdrawals)用户转账(存款+取款)

+-------------------------------+-------------------------------------------+---------+--------------------------------------------+------------+----------+------------+---------+-----------+----------------+--------------------------------------------------------------------+---------------------------+----------------------------------+--------------+------------------------------+
|              PK               |                    SK                     | Account |                  Address                   | AddressTag | Exchange | Instrument | Network | Quantity  | TransactionFee |                           TransactionId                            |       TransferDate        |            TransferId            | TransferType |          UpdatedAt           |
+-------------------------------+-------------------------------------------+---------+--------------------------------------------+------------+----------+------------+---------+-----------+----------------+--------------------------------------------------------------------+---------------------------+----------------------------------+--------------+------------------------------+
| Exchange#Binance#Account#main | TransferDate#12/17/2022 4:59:12 PM +02:00 | main    | 0xF76d3f20bF155681b0b983bFC3ea5fe43A2A6E3c | null       | Binance  | USDT       | ETH     | 97.500139 |            3.2 | 0x46d28f7d0e1e5b1d074a65dcfbb9d90b3bcdc7e6fca6b1f1f7abb5ab219feb24 | 2022-12-17T16:59:12+02:00 | 1b56485f6a3446c3b883f4f485039260 |            0 | 2023-01-28T20:19:59.9181573Z |
| Exchange#Binance#Account#main | TransferDate#12/17/2022 5:38:23 PM +02:00 | main    | 0xF76d3f20bF155681b0b983bFC3ea5fe43A2A6E3c | null       | Binance  | USDT       | ETH     | 3107.4889 |            3.2 | 0xbb2b92030b988a0184ba02e2e754b7a7f0f963c496c4e3473509c6fe6b54a41d | 2022-12-17T17:38:23+02:00 | 4747f6ecc74f4dd8a4b565e0f15bcf79 |            0 | 2023-01-28T20:20:00.4536839Z |
| Exchange#FTX#Account#main     | TransferDate#12/17/2021 5:38:23 PM +02:00 | main    | 0x476d3f20bF155681b0b983bFC3ea5fe43A2A6E3c | null       | FTX      | USDT       | ETH     |        20 |            3.2 | 0xaa2b92030b988a0184ba02e2e754b7a7f0f963c496c4e3473509c6fe6b54a41d | 2021-12-17T17:38:23+02:00 | 4747f6ecc74f4dd8a4b565e0f15bcf79 |            0 | 2023-01-28T20:20:00.5723855Z |
| Exchange#FTX#Account#main     | TransferDate#12/19/2022 4:59:12 PM +02:00 | main    | 0xc46d3f20bF155681b0b983bFC3ea5fe43A2A6E3c | null       | FTX      | USDT       | ETH     |        15 |            3.2 | 0xddd28f7d0e1e5b1d074a65dcfbb9d90b3bcdc7e6fca6b1f1f7abb5ab219feb24 | 2022-12-19T16:59:12+02:00 | 1b56485f6a3446c3b883f4f485039260 |            0 | 2023-01-28T20:20:00.5207119Z |
+-------------------------------+-------------------------------------------+---------+--------------------------------------------+------------+----------+------------+---------+-----------+----------------+--------------------------------------------------------------------+---------------------------+----------------------------------+--------------+------------------------------+
public async Task<UserTransferDto?> GetLastAsync(string exchange, string account)
{
    var queryRequest = new QueryRequest
    {
        TableName = TableName,
        KeyConditionExpression = "#pk = :pk",
        ExpressionAttributeNames = new Dictionary<string, string>
        {
            { "#pk", "PK" }
        },
        ExpressionAttributeValues = new Dictionary<string, AttributeValue>
        {
            { ":pk", new AttributeValue { S = $"Exchange#{exchange}#Account#{account}" } }
        },
        ScanIndexForward = false,
        Limit = 1
    };

    var response = await _dynamoDb.QueryAsync(queryRequest);
    if (response.Items.Count == 0)
    {
        return null;
    }

    var itemAsDocument = Document.FromAttributeMap(response.Items[0]);
    return JsonSerializer.Deserialize<UserTransferDto>(itemAsDocument.ToJson());;
}

A little edit:一点编辑:

I realized I needed the transfer type too, so I changed SK to TransferType#Withdraw#TransferDate#2022-12-17 14:59:12我意识到我也需要传输类型,所以我将SK更改为TransferType#Withdraw#TransferDate#2022-12-17 14:59:12

and now the code looks like:现在代码如下所示:

public async Task<UserTransferDto?> GetLastAsync(string exchange, string account, TransferType transferType)
{
    var queryRequest = new QueryRequest
    {
        TableName = TableName,
        KeyConditionExpression = "#pk = :pk and begins_with(#sk, :sk)",
        ExpressionAttributeNames = new Dictionary<string, string> { { "#pk", "PK" }, { "#sk", "SK" } },
        ExpressionAttributeValues = new Dictionary<string, AttributeValue>
        {
            { ":pk", new AttributeValue { S = $"Exchange#{exchange}#Account#{account}" } },
            { ":sk", new AttributeValue { S = $"TransferType#{transferType}" } }
        },
        ScanIndexForward = false,
        Limit = 1
    };

    var response = await _dynamoDb.QueryAsync(queryRequest);
    if (response.Items.Count == 0)
    {
        return null;
    }

    var itemAsDocument = Document.FromAttributeMap(response.Items[0]);
    return JsonSerializer.Deserialize<UserTransferDto>(itemAsDocument.ToJson());
}

My personal attitude - not to change anything if:我个人的态度——如果出现以下情况,我不会改变任何事情:

  1. It works right now它现在有效
  2. I don't see any future risks on my system我没有看到我的系统有任何未来的风险
  3. There is no benefits on performance/durability/maintenance/ease of support在性能/耐用性/维护/易于支持方面没有任何好处

And coming to your question I don't see how merging two tables can help you.对于您的问题,我看不到合并两个表对您有何帮助。

I'd challenge that your table structure won't help you to cover these queries:我会质疑您的表结构不会帮助您涵盖这些查询:

  • Get the last user transfer for a given exchange and an account name.获取给定交易所的最后一次用户转账和账户名。
  • Get all user trades by date range.按日期范围获取所有用户交易。
  • Get all user transfers by date range.按日期范围获取所有用户转移。

If I understand correctly you don't need to query anything by your current PK => why did you choose this PK?如果我理解正确的话,你不需要通过当前的 PK 查询任何内容 => 你为什么选择这个 PK? Of course you can solve it by using GSI but you won't get them for free and if you can restructurise your table to make your 3 queries easier I'd do that.当然,您可以使用 GSI 来解决它,但您不会免费获得它们,如果您可以重组您的表以使您的 3 个查询更容易,我会这样做。

Hope I answered your question.希望我回答了你的问题。 Good luck, have fun)祝你好运,玩得开心)

A query for the newest/latest item for a given partition key (pk) is possible if the sort key (sk) has a lexicographically sortable date/time representation eg ISO 8601. This is possible because items with the same pk value are stored in sorted order by sk.如果排序键 (sk) 具有按字典顺序排序的日期/时间表示,例如 ISO 8601,则可以查询给定分区键 (pk) 的最新/最新项。这是可能的,因为具有相同 pk 值的项存储在按sk排序。

To do this, simply issue a query for the pk + sk prefix, and supply Limit=1 and ScanIndexForward=False.为此,只需发出 pk + sk 前缀的查询,并提供 Limit=1 和 ScanIndexForward=False。 For example:例如:

KeyConditionExpression = "pk=:pk and begins_with(sk, :trade_prefix)"
Limit=1
ScanIndexForward=False

You can query for items with a given partition key (pk) and a sort key (sk) within a given range of dates using a key condition expression on the query which looks like a BETWEEN b and c.您可以在给定的日期范围内使用给定的分区键 (pk) 和排序键 (sk) 查询项目,在查询中使用键条件表达式,看起来像a BETWEEN b and c.

For example:例如:

KeyConditionExpression = "pk=:pk and sk between :t1 and :t2"

On the question of using DynamoDB as a simple key/value store where the value is a JSON blob, it depends on your access requirements.关于将 DynamoDB 用作简单的键/值存储(其中值为 JSON blob)的问题,这取决于您的访问要求。 Some reasons not to have single JSON blob are that:没有单个 JSON blob 的一些原因是:

  1. any update to the item means you have to rewrite the whole item which costs more WCUs对项目的任何更新都意味着您必须重写整个项目,这会花费更多的 WCU
  2. you can't create GSIs on most of the item's attributes because they're not top-level您无法在商品的大部分属性上创建 GSI,因为它们不是顶级属性
  3. it can makes concurrent puts more challenging它可以使并发放置更具挑战性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM