【问题标题】:What would be most elegant way to replicate data contents periodically into a MySQL table?将数据内容定期复制到 MySQL 表中的最优雅的方法是什么?
【发布时间】:2014-12-04 11:21:26
【问题描述】:

我需要从 API 路由解析内容并插入 MySQL 数据库。解析内容的目的是将 API 中的数据复制到我的数据库表中。

我需要使用计划的 cron 作业每天(在指定时间)检查 API 响应,并且应该获取所有可用记录并将其插入数据库中。每次响应都可能发生变化,它应该反映在API。

没有任何字段可以考虑用于制作唯一 ID。

我无法搜索和排序,因为它不是单独的更新任务,因此我们应该从 API 中“复制”数据,而不是“更新”记录。我们需要考虑,

  • 从 API 响应中删除已删除记录,
  • 更新修改的记录字段和
  • 还有新记录的插入。

考虑一个例子:

在第 1 天,

让 API 可用的记录为 A1、A2、A3、A4

这些记录之间可能有重复的条目。

我们将解析 API 响应并按原样插入可用的记录。该脚本将获取记录(A1、A2、A3、A4)并将其插入到我们的表中。

因此我们的表将包含记录:(A1, A2, A3, A4)

考虑第二天,

让API可用的记录为A1,A2,A3,A5,A6 -

可能的情况:

  • 每条记录 A1、A2 和 A3 的字段值可以更新为 第一天

  • A4 现已从 API 响应中移除

  • 现在添加新记录 A5、A6。

在这种情况下,我们的目标是更新表,使其仅包含记录 A1、A2、A3、A5、A6 及其更新值。

数据应该是结构化的。API中有特定的字段需要解析和获取。我们无法估计更改的频率,并且要求每天更新。

响应字段值可能会更改,但结构不会更改。应为其提取值的字段将保持不变,只有更改会影响字段值。

目前大约有2000条记录,很快就会增加到5000条。

不应有任何停机时间,因为此表中的服务由另一个应用程序实时使用。 编辑: 我正在解析 API 响应并将其插入到一个表中,该表充当另一个应用程序的主表。该应用程序需要在没有任何停机时间的情况下工作,即;即使我们在表上执行一些操作(重新创建表),停机时间也应该最少。

示例 API 响应:

[
    {
        "company": "XYZ",
        "company_id": 123,
        "owner": null,
        "owner_id": null
    },
    {
        "company": null,
        "company_id": null,
        "owner": "ABC",
        "owner_id": 321
    },
    {
        "company": "XYZ",
        "company_id": 123,
        "owner": null,
        "owner_id": null
    },
    {
        "company": null,
        "company_id": null,
        "owner": "PQR",
        "owner_id": 100
    }
]

数据库表应按照给定的方式复制 API 响应 - 无论 API 结果中是否存在任何错误/重复。API 响应无法事先预测,也没有任何直接字段可被视为一个唯一的 ID。

我正在使用 PHP-MySQL.API 响应是 JSON 格式。我在 SO 中看到过类似的问题,但它不能很好地满足我的要求,也没有可接受的答案。

What is the best way to periodically load data into table

从上述问题看来,我的情况似乎也需要使用某种临时表。

考虑到安全性、性能和无停机时间,解决这个问题的最优雅的方法是什么。在这种情况下,什么是最好的 MySQL 存储引擎(InnoDB/MYISAM)? 请指教。

【问题讨论】:

  • 您自己是否对本地副本中的数据库记录执行任何操作?如果没有,你可以在一个新表中导入新的数据结构,一切都完成后,做一点切换;当前表重命名为'xxxx_old',新表重命名为'xxxx'
  • @SurabhilSergy 当您获得新数据的更新时,是否需要本地副本中的旧数据?
  • @SurabhilSergy 我的意思是当您发出 API 请求时,API 会返回所有数据 2000 条记录吗?
  • 如果您想实时更新,您可以在本地副本中添加一个标志(类似于更新标志)。更新前,将所有记录设置为updated = 0。更新和插入将updated 标志设置为1,然后删除所有仍设置为updated = 0 的记录
  • 我确实添加了它作为答案,有一个小的附录,看看=)

标签: php mysql sql performance optimization


【解决方案1】:

我不太确定您的要求是什么,以及为什么 RichardBernards 的回答不适合您的需求。

您谈到一个包含少于 10.000 个 json 对象的数组,从而导致一个少于 10.000 行的表。 json 和最后一行之间的差异很容易放入内存中。您可以生成一个长 sql 脚本,其中包含应用更新所需的所有插入、更新和删除,并在一个事务中应用更新。

需求中没有明确的一点是提到了“实时”,提到了这个“每日”更新,这显然是一个批处理类型。您将更新描述为批量更新,但提到有实时要求?

如果您确实需要持续访问而不是实时数据,您可以使用新值构建一个新表,并按照https://dba.stackexchange.com/questions/22108/how-do-i-swap-tables-in-mysql 中的说明重命名这些表。假设您有一个名为“CurrentValues”的表,其中包含系统其余部分处理的数据,然后您构建一个表“NewValues”,它看起来就像您的“CurrentValues”表在瞬间的样子。然后在一个原子事务中重命名“currentValues”->“oldvalues”、“newValues->currentValues”。然后执行删除“oldvalues”。如果您“幸运”,来自 API 的数据是一个完整的列表,可以插入到您的“NewValues”表中。

【讨论】:

  • 我正在解析 API 响应并将其插入到一个表中,该表充当另一个应用程序的主表。该应用程序需要在没有任何停机时间的情况下工作,即;即使我们在表上执行一些操作(重新创建表),停机时间也应该最少。
【解决方案2】:

为了实时更新:

您可以在本地副本中添加一个标志(类似于更新的 旗帜)。更新前,将所有记录设置为 updated = 0。
API结果解析过程,一个update和insert设置updated标志 1.解析过程完成后,删除所有记录 仍然设置为updated = 0

当您以特定顺序接收 id 时,您可以简化此过程(您可以通过首先从数据库中以相同顺序检索一个集合来知道缺少哪一个)。比您几乎可以即时删除丢失的内容。

在您的示例中显示这一点;第二天您收到A1,A2,A3,A5,A6。您从本地副本加载前 5 条记录(因为只有 4 条,您最终会得到 A1,A2,A3,A4)。
您像这样迭代 API 接收到的值(伪代码):

$difference = array_diff($localCopyItems, $apiItems);
// $difference now contains all items present in $localCopyItems which are not present in $apiItems
foreach($difference as $deletionItem) {
    // delete $deletionItem from database
}

当然,这是一个过于简单的例子,但这就是它的要点。

【讨论】:

  • 我不确定有响应的订单?在这种情况下如何有效地删除?
  • @SurabhilSergy 我已经用一些伪解码更新了答案以解释我的意思。
  • 没有可以归类为唯一 ID 的字段。只有当我得到一些唯一的 ID 时,我们才能比较本地副本和 API 项目!
  • @SurabhilSergy 您将如何更新现有记录?在示例中,我可以看到company_idowner_id。在我看来,这两者的组合呈现了一个唯一的 ID,对吧?
  • 响应每天都在变化,那么我们如何构建一些统一的唯一 ID。这里的情况是,company_id(null)+owner_id(null) 不等于 company_id(null)+owner_id不等于 company_id+owner_id(null) 不等于 company_id+owner_id
猜你喜欢
  • 2011-04-01
  • 2012-07-09
  • 2023-03-05
  • 2017-05-08
  • 2011-08-16
  • 2019-11-22
  • 2010-12-30
  • 1970-01-01
  • 2011-03-14
相关资源
最近更新 更多