【问题标题】:mysql optimization - copy or serialized old rowsmysql 优化 - 复制或序列化旧行
【发布时间】:2017-03-04 12:40:37
【问题描述】:

假设我有一个包含这些列的简单表格:

|编号 |用户 ID | order_id |

每月大约有 1,000,000 行插入到该表中,并且很明显 user_id 和 order_id 之间的关系是 1 到 M。

会计问题所需的上个月记录和其他仅用于向用户显示订单历史记录。要归档上个月之前的记录,我有两个选择: 首先,创建一个类似的表,每个月将旧记录复制到它。这样它就会根据订单的增长每个月变得越来越大。 其次,创建如下表:

|编号 |用户 ID | order_idsss |

每个月,对于要插入此表的每一行,如果存在user_id,只需更新order_ids,并将新的order_id 添加到order_ids 的末尾。 在这个解决方案中,表中的行数会根据用户增长比例而变大。

假设对于每个解决方案我们都有一个关于 user_id 的索引。 . 现在的问题是,在服务器负载的情况下,哪个对 SELECT all order_ids per user 更优化。 第一个比第二个有更多的记录,但是在第二个中,需要一些编程语言来拆分 order_ids。

【问题讨论】:

  • 为各种订单 ID 存储 CSV 数据听起来是个坏主意。如果您在第一个表上设置了索引,可能在时间戳上,查询应该不会那么糟糕。我投票给第一个选项。
  • 同意@Tim。永远不要在一行中存储多个值。这是第一个规范化原则。

标签: mysql database-optimization


【解决方案1】:

第一个选择是更好的选择,在您显示的两个中。恕我直言,我应该说您的第二选择是一个糟糕的想法

MySQL(具有所有 SQL dbms 系统)在处理大量统一布局(即规范化)数据的行方面表现出色。

但是,您最好的选择是除了创建适当的索引以方便按日期或用户查找订单历史记录之外什么都不做。将所有数据保留在此表中并优化查找。

在此表包含至少 5000 万行(至少四年的数据)之前,您花在重新编程系统以将其拆分为当前版本和存档版本所花费的时间将远远超过仅仅保持在一起。

如果您需要帮助确定您需要哪些索引,您应该提出另一个问题来显示您的查询。从这个问题中不清楚您如何按日期查找订单。

【讨论】:

    【解决方案2】:

    在 1:many 关系中,不要创建额外的表。而是让user_id 成为Orders 表中的一列。此外,这可能有助于提高性能:

    PRIMARY KEY(user_id, order_id),
    INDEX(order_id)
    

    “月”是日历月吗?还是“30 天前到现在”?

    如果是日历月,请考虑 PARTITION BY RANGE(TO_DAYS(datetime)) 并拥有不断增加的每月分区列表。但是,不要提前创建未来几个月;在需要它们之前创建它们。更多详情:http://mysql.rjweb.org/doc.php/partitionmaint

    注意:这需要在 PK 末尾添加 datetime

    在 4 年的数据量(48 个分区)上,是时候重新思考问题了。 (我建议不要超过这个数量的分区。)

    阅读“可传输表空间”。这可能会成为您“归档”过程的一部分。

    使用 InnoDB。

    使用该分区,其中任何一个都变得相当有效:

    WHERE user_id = 123
      AND datetime > CURDATE() - INTERVAL 30 DAY
    
    WHERE user_id = 123
      AND datetime >= '2017-11-01'  -- or whichever start-of-month you need
    

    以上每一项都将最多访问一个非空分区,超过所需的月数。

    如果您想进一步讨论这个问题,请提供SHOW CREATE TABLE(任何变体),以及一些重要的SELECTs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-20
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多