【问题标题】:Mysql put record between two records orderMysql将记录放在两条记录之间的顺序
【发布时间】:2020-07-08 21:11:01
【问题描述】:

这里是记录,我们希望在 #3 和 #4 之间移动 id #1

id  title   sort
1     a      1
2     b      2
3     c      3
4     d      4
5     e      5
6     f      6

方法一:

获取#3 排序号并对其加 1,并用它更新#1 排序,这样我们就有了

id  title   sort
1     a      4
2     b      2
3     c      3
4     d      4
5     e      5
6     f      6

然后加上 1 到 #4 排序以及之后的任何记录

我们有

id  title   sort
1     a      4
2     b      2
3     c      3
4     d      5
5     e      6
6     f      7

排序后

id  title   sort
2     b      2
3     c      3
1     a      4
4     d      5
6     e      6
6     f      7

它工作正常,但假设我们有 2,000,000 条记录,并且所有记录都必须更新......

方法二

得到 #3 和 #4 的总和排序并除以 2 => (3+4)/2=3.5 并将其用于#1 排序

id  title   sort
2     b      2
3     c      3
1     a      3.5
4     d      4
5     e      5
6     f      6

它也可以正常工作,但想象一下这种操作的数千次会产生像 3.99999999999 这样的大浮点数,过了一会儿它就很可怕

是否有任何 mysql/mariadb 技巧或方法可以做到这一点?

【问题讨论】:

  • 您可以使用浮点数,然后定期进入表格并规范化值。
  • @GordonLinoff 规范化大数据,让 mysql 宕机……
  • 请描述此类操作的必要性。可能有一种完全不同的方法效果更好。
  • @RickJames 这是用于购物网络应用程序的后端部分,在前视图中,用户可以通过拖放(角度)对产品进行排序,并且在用户放下每个产品后必须保存订单,这是漏洞前后项目 -> github.com/shopiddev

标签: mysql sql mariadb


【解决方案1】:

您的“将它放在项目之间的一半”方法可能是最好的。

让我们使用BIGINT UNSIGNED,因为它在 8 个字节中为您提供 64 位。不太好:DOUBLE 会在 8 个字节中为您提供 53 位,以及一些有趣的指数业务。 DECIMAL 以更多字节为代价为您提供更多位,同时并未消除对以下代码的需求。

  • 您知道根据用户输入将其放在“之后”的哪一行吗?
  • 使用ORDER BY ... ASC LIMIT 1发现后面的行。
  • 平均两个值;检查 avg 是否等于其中任何一个 - 如果是,则说明情况不佳。

题外话... 2M 行。从 2K、4K、6K 等作为sort 值开始(2M*2K = 4G,BIGINT UNSIGNED 的限制。)

这表示您可以在任何相邻对之间挤压 2K 个项目。但是,在最坏的情况下,恰好在第一个值之后重复插入,在撞墙之前只有 11 次插入。 11 ~= log2(2000)。也就是说,重新排序可能很快,但最多 11 次中的 1 次,这将是昂贵的。

(请不要在 2K 表示 2000 和 2048 之间争辩;这与算法无关。)

那么,当没有空间插入新的排序值时该怎么办?重建数字会锁定表(2M 行)“太长”,所以让我们尽量避免这种情况。

这个怎么样:

获取前后的 10 行(2 个带有 ORDER BY 和 LIMIT 的 SELECT)。修复那些sort 值,使它们均匀分布。

  • 点击表格的开头或结尾可能没有问题;它会少于 20 行。并且有一个无声的 0 和 4G-1 界限。
  • 如果 20 行不够,那就扩大跨度。
  • 在事务中执行所有这些(包括原始、简单、中途代码)。
  • 在所有(?)SELECTs 上使用FOR UPDATE,以便阻止其他线程。
  • 检查死锁。如果遇到,完全重新开始。 (第二次尝试可能会发现中途尝试工作正常——因为其他一些线程完成了将排序值展开。)

时间:

  • 中途情况,即使有事务,也可能需要一毫秒左右。
  • 尽管锁定并更新了 20 行,但更复杂的情况不会花费太多时间。
  • 您可能每秒可以处理 1K 次操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多