在数据库中的一组记录上存储排序顺序的最有效方法是什么?

swe*_*e44 19 mysql algorithm performance database-design

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

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

例如,我有一个数据库表"照片",大约有一百万条记录:

photos id:int,userid:int,albumid:int,sortorder:int,filename:varchar,title:varchar

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

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

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

如果单个图库中有数千张照片并且排序顺序发生了变化,会发生什么?

TMS*_*TMS 19

如何使用integer定义订单的列呢?默认情况下,您指定数字*1000,如1000,2000,3000 ....如果您在1000和2000之间移动3000,则将其更改为1500.因此,在大多数情况下,您根本不需要更新其他数字.我使用这种方法,效果很好.您也可以使用double但是您无法控制精度和舍入误差,因此请不要使用它.

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

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

  • 无论您使用哪种算法,*在某些时候*您都必须确定是否有空间用于新订单.时间戳/日期具有有限的准确性,它只不过是这里提出的整数解决方案只有更多的数字.您可以轻易地争辩说,而不是1000,2000,3000,您使用1000000,2000000,3000000.您只是在这里推迟"问题".无论如何,请带这个聊天.评论是为了改进/解决问题的答案,而不是找出最佳/良好/可接受的解决方案. (3认同)

Bry*_*ves 5

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