Nud*_*oll 4 database activerecord database-design ruby-on-rails relational-database
在我的应用程序中,用户可以按照他们选择的顺序重新排列他们喜爱的书籍.
我的数据库中有一个"书籍"表,每本书都有一行.目前,有一个名为"position"的整数列,用于存储每本书的位置:1为顶级书籍,2为下一本书,等等.
问题是,如果有人将书从位置#11000拖到位置#1,那么我必须对数据库进行11,000次更新.这似乎效率低下.有一个更好的方法吗?
我曾经有过的一个想法就是让另一个名为"book_sort_orderings"的表或其他东西,每个用户都有一行.一列是一个巨大的文本列,用于存储书籍ID的排序列表.然后,当用户重新排列书籍时,我可以将此值拉出到我的代码中,在那里执行重新排列,并更新数据库行.当然,每当添加或删除一本书时,我都必须更新这个数组.这是处理事情的"正确"方式吗?或者有什么聪明的我可以做的事情来加快速度而不改变我目前的设置?
假设您以"批量"方式执行此操作(而不是为每行进行单独的数据库往返),您会惊讶于一个体面的DBMS可以快速更新11,000行.
但是如果你想避免这种情况,那就使用旧的BASIC技巧(从BASIC的时候还有行号):留下空白!
而不是使用职位:1, 2, 3, 4, 5 etc...使用10, 20, 30, 40, 50 etc....
因此,当您需要将第一个项目移动(比方说)到倒数第二个位置时,只需修改10到41,您将最终得到:20, 30, 40, 41, 50 etc....显然,如果差距被完全填满,你需要做一些摆弄,但这个策略应该能够几乎消除大量的UPDATE.
另一种可能性是实现双向链表:而不是订单,保留前一个和下一个项的ID.重新排序可以通过简单地"重新链接"ID来完成,就像在内存列表中一样.不幸的是,您还会阻止DBMS直接对项目进行排序(至少没有笨拙且可能效率低下的递归查询) - 您必须在应用程序级别进行排序,所以我建议再次对它进行排序
一列是一个巨大的文本列,用于存储书籍ID的排序列表.
请不要这样做.您违反了1NF并且有很好的理由不这样做,包括数据一致性和性能(您必须重写整个字段以对其中的任何部分进行任何单个更改).
您当前的解决方案似乎不适用于多个用户设置.如果在Book表格中设置了图书的订单,那么它对所有用户来说都不是永久性的吗?
正如其他人所提到的,通常最好将数据标准化,这需要您添加另一个表,就像您所建议的那样.所以你可以有一张新BookOrdering桌子.所以它有一个book_id,一个user_id和一个position列.这样,每个用户和每本书都有一个指定的位置.
因此会有一个默认排序(不会存储在此表中),但用户可以更改顺序.该表仅记录默认值的更改.如果要加载用户的书籍,首先要检查此表格中是否有某个user_id,然后相应地切换/调整顺序.