当数据重复且我没有时间戳时避免重复插入的建议

Posted

技术标签:

【中文标题】当数据重复且我没有时间戳时避免重复插入的建议【英文标题】:Advice on avoiding duplicate inserts when the data is repetitive and I don't have a timestamp 【发布时间】:2014-02-21 22:58:25 【问题描述】:

详情

这是一个相当奇怪的场景。我正在尝试存储我无法控制的服务的销售记录。我只是在访问一个 URL 并存储它返回的 json。它返回一个项目的最后 25 次销售,按成本排序,并且这些值似乎将在那里最多停留 10 小时。最大的问题是这些值没有时间戳,所以我不能非常准确地推断项目在列表中的存在时间以及它们是否重复。

示例:

假设我在下午 1 点查看此网址并得到这些结果

+--------+----------+-------+
| Seller | Category | Price |
+--------+----------+-------+
| Joe    | A        |  1000 |
| Mike   | A        |  1500 |
| Sue    | B        |  2000 |
+--------+----------+-------+

下午 2 点我得到了值,它们是:

+--------+----------+-------+
| Seller | Category | Price |
+--------+----------+-------+
| Joe    | A        |  1000 |
| Sue    | B        |  2000 |
+--------+----------+-------+

这意味着 Mike 的销售是 10 多小时前的,并且价值已超时

下午 3 点:

+--------+----------+-------+
| Seller | Category | Price |
+--------+----------+-------+
| Joe    | A        |  1000 |
| Joe    | A        |  1000 |
| Sue    | B        |  2000 |
+--------+----------+-------+

这意味着乔在过去 10 小时内的某个时间进行了 1 次 1000 美元的销售,但自我们上次检查以来,他还以相同的价格进行了另一次销售。

我的目标:

我希望能够将每个独特的销售存储在数据库中一次,但如果确实发生,则允许多次销售(如果原始计划太复杂,我可以每天只允许 1 次销售) .我意识到没有时间戳和超过 25 次销售的潜力会导致价值提前消失,结果不会 100% 准确,但我希望能够至少大致了解销售情况发生。

到目前为止我做了什么:

到目前为止,我已经创建了一个表,其中包含上述列以及我将其插入数据库时​​的 DATETIME,然后是我自己的插入日期的字符串版本 (YYYYMMDD)。我将卖家、类别、价格和我的 YYYYMMDD 日期作为我的主键。我打算在插入之前只搜索不到 10 小时前的条目,但我每小时要对大约 50k 个条目执行此操作,所以我担心这对系统来说负担过大(但我不知道,mysql 不是我的强项)。我目前正在做的是我已经设定了规则,我可以只允许每天记录 1 次销售(这是通过我的 pk 是我上面提到的值的组合来完成的),但我发现晚上 10 点进行的销售最终会在第二天凌晨 1 点添加重复项,因为该值尚未超时,并且由于日期已更改,它再次被认为是唯一的。

你会怎么做?

我很想知道你将如何实现这样的目标。我愿意接受所有建议,如果解决方案导致卖家每天只有 1 次唯一销售,我可以接受。

非常感谢大家,我已经关注这个问题一个星期了,我觉得是时候重新审视它了。任何 cmet 都表示赞赏!

更新 - 在玩弄我的想法时,我基本上想每次在数据库中禁用给定伪 pk(卖家类别价格)的条目 10 小时,但它发生了我,如果我有一个两阶段的插入过程怎么办。每当我得到 unqiue 值时,我都可以将它们放在存储数据和输入时间戳的第一阶段表中。如果尝试插入重复项,我会忽略它。 10 小时后,我将这些值从第 1 阶段表移动到我的最终值表,从而在 10 小时后重新允许重复销售的条目。我认为这甚至可以允许多次销售,时间重叠,只是有点延迟。假设销售发生在下午 1 点和 6 点,下午 1 点的条目将在第 1 阶段表中直到晚上 11 点,然后一旦移动,下午 6 点的条目将被记录,只是晚了 5 小时(不幸的是,该值最终会减少 5 小时也插入日期,这可能会将销售推迟到第二天,但我可以接受)。这避免了我担心在每次插入时查询数据库以查找重复项的大问题。它唯一复杂的是实时查看数据,但我认为从 2 个不同的表进行查询应该不会太糟糕。小伙伴和小伙伴们怎么看?看看这个方法有什么缺陷吗?

【问题讨论】:

这些条目是否总是存在整整十个小时,或者它们是否有可能更早消失?如果它们都存活了大约 10 个小时,您可以通过每 10 个小时查询该站点并假设您永远不会得到重复来获得一个很好的近似值。 我同意 Xavier 的想法——这也是另一个建议——说对于您插入表中的每条新记录,您为其获取主键,将其与所有数据一起上传到第二个表中对于上面的交易呢?因此,在您的示例中,假设 Mike 的自动编号 ID 为 50,一旦他上传了一条记录,则将 FK 为 50 的记录放入第二个表中,并用 Joe 的数据填充它。在每次上传之前与该表进行比较,您就可以降低重复的可能性。我不知道任何 JSON,但我喜欢这个问题 该 url 返回最后 25 个条目的最长时间为 10 小时,因此在忙碌的一天有可能在 10 小时过去之前从列表中删除条目。遗憾的是,每次返回数据时都会对其进行排序,因此我无法根据它在列表中的位置来推断任何序列数据。谢谢你的这些建议,它给了我更多的想法,我几乎可以完全考虑,但还没有把我的手指放在我的手指上;) 【参考方案1】:

问题不在于如何存储数据,而在于如何首先识别哪些记录是不同的(尽管事实上没有时间戳或事务 ID 来区分它们)。如果您可以区分逻辑上不同的记录,那么您可以创建不同的合成 ID 或时间戳,或者执行您喜欢的任何操作来存储数据。

我推荐的方法是经常对 URL 进行采样。如果您能够始终如一地以比更新数据快得多的速度收集数据,那么您将能够通过注意它们之前的记录顺序来确定之前观察过哪些记录。

假设每条记录中的字段都有一些可变性,那么在 10 小时内出现 5 条或 10 条或 15 条记录的相同序列是非常不可能的。因此,只要您足够快地对数据进行采样,每次只翻转 25 条记录中的一小部分,您的结论就会非常有把握。这类似于在“猎枪”算法中对 DNA 进行测序的方式。

您可以通过仅采集样本并测量您看不到足够先前记录的频率来确定样本需要的频率 - 调高或调低采样频率。

【讨论】:

不幸的是,我每小时都会查看大约 3,300 件商品,每件商品可以带来 25 笔销售额,因此我最多可以达到 80k 值来处理,我认为这将取消进行快速观察的选项(在 avg i在我的脚本上查看大约 5 分钟的运行时间,因为它正在查询 3,300 个 url 以获取 json 数据)。关于检查序列,他们遗憾地返回按价格排序的数据,这否定了任何可能固有地提供了一些有形序列信息的先进先出/队列排序。 排序行为没有帮助,但您仍然可以使用检查数据时代的基本方法来确定哪些记录是新的还是旧的。如果这是您唯一可用的 API,那么您有一个触摸行可以锄头,但它仍然可以工作。如果脚本的整体运行时间是一个问题,有很多方法可以解决这个问题——将脚本与子进程并行化,或者运行脚本的多个实例,还有很多其他方法。

以上是关于当数据重复且我没有时间戳时避免重复插入的建议的主要内容,如果未能解决你的问题,请参考以下文章

如何避免插入重复记录?

插入时间戳时的 H2 org.h2.jdbc.JdbcSQLSyntaxErrorException

java.sql.SQLException:ORA-00932:不一致的数据类型:预期 DATE 在插入 Null 时间戳时得到 BINARY

SQLite 避免 android 中的重复条目

创建PHP时间戳以插入mysql数据库[重复]

Laravel 迁移 - 创建时间戳时的问题