mysql - Mysql将记录放在两条记录之间的顺序
问题描述
这是记录,我们希望在 #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 技巧或方法可以做到这一点?
解决方案
您的“将其放在项目之间的一半”方法可能是最好的。
让我们继续吧,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 行不够,那就扩大跨度。
- 在事务中完成所有这些(包括原始的、简单的、中途代码)。
FOR UPDATE
在 all(?) 上使用,SELECTs
以便阻塞其他线程。- 检查死锁。如果遇到,完全重新开始。(第二次尝试可能会发现中途尝试工作正常——因为其他一些线程完成了将排序值展开。)
定时:
- 中途的情况,即使有事务,也可能需要一毫秒左右。
- 尽管锁定和更新了 20 行,但更复杂的情况不会花费更长的时间。
- 您可能每秒可以处理 1K 次操作。
推荐阅读
- wordpress - Wordpress wp_head 仅在以管理员身份登录时插入脚本
- javascript - 页面内 JavaScript 代码的 PHP 简单 HTML DOM 解析器
- asp.net-core - 等效于 ASP.NET Core 中的“FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest”
- kendo-ui-grid - Kendo ui 工具提示内容返回“e.uniqueSort 不是函数”错误
- python - 用于过滤的 Django 搜索表单
- python-3.x - Webscraping 不会用从所有页面询问的所有信息填充文件
- c# - android中的TextInputEditText没有获得焦点
- azure-data-explorer - 如何在 Kusto 函数中使用控制命令
- api - 如何使用客户电话号码将 whatsapp api 链接添加到电子邮件订单?
- java - Lightcouch 如何检查设计文档是否存在?