4

在我的应用程序中,用户可以按照他们选择的任何顺序重新排列他们最喜欢的书籍。

我的数据库中有一个“书籍”表,每本书都有一行。目前,有一个名为“位置”的整数列存储每本书的位置:1 表示最上面的书,2 表示下一本,等等。

问题是,如果有人将一本书从 #11000 位置拖到 #1 位置,那么我必须对数据库进行 11,000 次更新。这似乎效率低下。有一个更好的方法吗?

我的一个想法就是拥有另一个名为“book_sort_orderings”或其他东西的表,每个用户都有一行。其中一列将是一个巨大的文本列,其中存储书籍 ID 的排序列表。然后当用户重新排列书籍时,我可以将这个值提取到我的代码中,在那里执行重新排列,并更新数据库行。当然,任何时候添加或删除一本书,我都必须更新这个数组。这是做事情的“正确”方式吗?或者有什么聪明的方法可以在不改变当前设置的情况下加快速度吗?

4

3 回答 3

8

假设您以“批量”方式进行更新(而不是为每一行进行单独的数据库往返),您会惊讶于一个体面的 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...。显然,如果一个空白被完全填满,你需要做一些摆弄,但这种策略应该能够几乎消除大量的更新。


另一种可能性是实现双向链表:保留上一个和下一个项目的 ID,而不是 order。重新排序可以通过简单地“重新链接”ID 来完成,就像在内存列表中一样。不幸的是,您还会阻止 DBMS 直接对项目进行排序(至少没有尴尬且可能效率低下的递归查询) - 您必须在应用程序级别进行排序,所以我建议再次使用它


其中一列将是一个巨大的文本列,其中存储书籍 ID 的排序列表。

请不要那样做。您将违反1NF,并且有很好的理由不这样做,包括数据一致性和性能(您必须重写整个字段以对其任何部分进行任何单个更改)。

于 2012-11-16T01:48:34.493 回答
5

您当前的解决方案似乎不适用于多用户设置。如果这本书的顺序是在Book表格中设置的,那不是对所有用户都是永久的吗?

正如其他人所提到的,通常最好保持您的数据标准化,这将需要您添加另一个表,就像您建议的那样。所以你可以有一张新BookOrdering桌子。所以它有一个book_id,一个user_idposition列。这样,每个用户和每本书都有一个指定的位置。

因此会有一个默认排序(不会存储在此表中),但用户可以更改顺序。该表只会记录默认的更改。当您要加载用户的书籍时,您首先要检查此表中的某个 user_id,然后相应地移动/调整顺序。

于 2012-11-16T01:43:07.340 回答
4

使用几个 SQL 语句更新示例中的所有这些行并不难。您不需要在您的 DBMS 上触发 11,000 次更新(我假设这就是您想说的)。

首先,更新所有正在向前移动的书籍:

UPDATE book
SET position = position + 1
WHERE position < 11000
AND position >= 1

...然后设置您要移动的书的位置:

UPDATE book
SET position = 1
WHERE id = whatever
于 2012-11-16T01:44:11.307 回答