在数据库中的一组记录上存储排序顺序的最有效方法是啥? [关闭]

Posted

技术标签:

【中文标题】在数据库中的一组记录上存储排序顺序的最有效方法是啥? [关闭]【英文标题】:What is the most efficient way to store a sort-order on a group of records in a database? [closed]在数据库中的一组记录上存储排序顺序的最有效方法是什么? [关闭] 【发布时间】:2011-10-11 20:40:54 【问题描述】:

假设 php/mysql 但我不一定需要实际代码,我只是对它背后的理论感兴趣。

一个很好的用例是 Facebook 的照片库页面。您可以在页面上拖放照片,这会触发 Ajax 事件以保存新的排序顺序。我正在实现一些非常相似的东西。

例如,我有一个包含大约一百万条记录的数据库表“photos”:

照片 id:整数, 用户标识:整数, 白蛋白:int, 排序顺序:整数, 文件名:varchar, 标题:varchar

假设我有一个包含 100 张照片的相册。我将照片拖放到新位置,然后 Ajax 事件触发以保存在服务器上。

我是否应该将整个照片 ID 数组传回服务器并更新每条记录?假设输入验证为“WHERE userid=loggedin_id”,恶意用户只能乱用自己照片的排序顺序

我是否应该传递照片 ID、之前的排序索引和新的排序索引,检索这两个索引之间的所有记录,对它们进行排序,然后更新它们的顺序?

如果一个画廊中有数千张照片并且排序顺序发生了变化,会发生什么情况?

【问题讨论】:

【参考方案1】:

只使用定义顺序的integer 列怎么样?默认情况下,您分配数字 * 1000,例如 1000、2000、3000.... 如果您将 3000 在 1000 和 2000 之间移动,则将其更改为 1500。因此在大多数情况下,您根本不需要更新其他数字。我使用这种方法并且效果很好。你也可以使用double,但是你无法控制精度和舍入误差,所以不要使用它。

所以算法看起来像:假设您将 B 移动到 A 之后的位置。首先执行 select 以查看 A 旁边的记录的顺序。如果它至少比 +2 高A 的顺序然后您只需将 B 的顺序设置为介于两者之间。但是如果它只是高+1(A之后没有空格),你选择B的边界记录,看看这一边有多少空间,除以2,然后将此值添加到A之间的所有记录的顺序中和 B. 就是这样!

(请注意,对于包含多个查询的任何算法,您都应该使用事务/锁定,因此这也适用于这种情况。最简单的方法是使用 InnoDB 事务。)

【讨论】:

不就是Typo3使用的算法吗? IMO 这非常昂贵,因为您仍然需要查找许多数字,并且您还需要提供一个 Gui 来更改大数字的排序顺序。 你能解释一下,你为什么不赞成我的回答吗?你的评论完全出局了。我提供的算法比迄今为止这里提出的任何算法都要好! IMO 有一个更好的算法然后分配数字。我使用文件创建的时间戳,然后交换这个时间戳来排序。 无论您使用哪种算法,在某些时候您都必须确定是否有空间用于新订单。时间戳/日期具有有限的精度,它只不过是这里提出的整数解决方案,只是有更多的数字。您可以很容易地争辩说,您使用 1000000、2000000、3000000 而不是 1000、2000、3000。您只是在这里推迟了“问题”。无论如何,请拿这个来聊天。评论是为了让 cmets 改进/修复答案中的问题,而不是找出哪个解决方案是最好的/好的/可接受的。 @TMS 我知道这是一个老问题,但只是想知道你是否碰巧知道这叫什么算法? Wiki上有什么我可以查找以查看该算法的示例代码的内容吗?尽管我了解基本概念,但我无法解决这个问题。【参考方案2】:

存储为链表,sortorder是集合中下一个photo_id的外键引用。

【讨论】:

这对 UPDATE 很有用,但它是否提供了使用 ORDER BY 的高效 SELECT? @swese:选择将是连接集合减去您的 LIMIT ***.com/questions/1151286/… @swese44 在内存中对结果进行排序,因为无论如何您都将获取完整的结果集以将其显示给用户。 但是,如果您要显示分页结果,比如一次显示 20 个,如果一个画廊有数千张照片记录,那就不太好了。您必须从数据库中获取数千条记录,在内存中对它们进行排序,然后只显示其中的 20 条。真的似乎不太有效,至少在这种情况下。 我还没有看到一个包含数千张照片的画廊——从组织的角度来看,这似乎毫无用处。我无法想象有什么 UI 可以让你重新排列画廊中的图片,那么大画廊必须看起来像这样。【参考方案3】:

这可能是一个“链表”结构。

【讨论】:

【参考方案4】:

对我而言,第二种更新方法是可行的方法(仅更新更改的范围)。您提到“如果一个画廊中有数千张照片会发生什么……”,对我来说,这永远不会发生。让我们以您的 Facebook 为例。 Facebook 不会在一页上显示数千张照片,他们将其拆分为每页大约 10-20 张。

【讨论】:

【参考方案5】:

我在非关系数据库中执行此操作的方式是按所需顺序将照片 ID 列表存储在“相册”实体/记录中。对照片重新排序会导致列表重新排序,并且只写入一次数据库。

一些 SQL 数据库(例如 PostgreSQL)具有本地列表数据类型,但 MySQL 没有。您可以在 MySQL 上将列表序列化为字符串或二进制文件。

3rd-normal-form 训练有素的数据库专家会告诉您这是一种糟糕的方法,但 RDBMS 已针对 OLAP 类型查询进行了优化,其中查询灵活性比读取性能更重要。最好在编写 Web 应用时考虑到“重写,轻阅读”的策略,而这种非规范化正是符合这一要求的。

【讨论】:

是的,但这是一个“准备重,写轻”的情况。 99% 的点击都将被读取,与仅浏览页面的用户和蜘蛛相比,重新排序“写入”点击的数量将非常低。如果每次加载图库页面时都需要进行额外的查询以获取照片记录的顺序,然后才能查询具有分页偏移量的实际照片记录,我不确定这种折衷是否值得。 @swese44 但它不需要额外的查询 - 你已经在加载画廊记录了。

以上是关于在数据库中的一组记录上存储排序顺序的最有效方法是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

(预)处理存储在 json 中的大型数据集的最有效方法是啥?

在数据库中存储标签的最有效方法是啥?

按时间对字典中的字典进行排序的最有效方法是啥(对于评论树)?

将数千条记录插入表中的最有效方法是啥(MySQL,Python,Django)

从sql列中拆分数据并将其保存在sql存储过程中的另一个表中的最有效方法是啥[重复]

mysql中“group by、having、order by、limit”的顺序及用法是啥?