【问题标题】:What is the best approach to insert a record between two sequencial rows?在两个连续行之间插入记录的最佳方法是什么?
【发布时间】:2015-08-10 16:41:45
【问题描述】:

我有一个简单的顺序表,例如:

  ID   | Name | Rank
=======+======+=====
  327  | Ali  | 1
-------+------+-----
  846  | Sara | 2
-------+------+-----
  657  | Dani | 3
-------+------+-----
         ...

ID 是主键并被索引,Rank 也被索引。我有几条这样的记录,我想要的是在SQL Server 的该表的记录之间插入一条记录,以保持其序列而不破坏排名。

例如,我将Sahar by 插入到上表中,排名为 2,这会导致排名更高,所以:

  ID   | Name | Rank
=======+======+=====
  327  | Ali  | 1
-------+------+-----
  196  | Sahar| 2     ----> Inserted
-------+------+-----
  846  | Sara | 3
-------+------+-----
  657  | Dani | 4
-------+------+-----
         ...

我已经搜索并找到了一些解决方案,例如:

UPDATE TABLE table SET Rank += 1 WHERE Rank >= 2;
INSERT INTO TABLE (Rank, ...) VALUES (2, ...);

在这个answer,或者其他方法可能是this answer。以及我找到的其他一些答案,但所有这些答案都在运营中付出了沉重的代价。

我也可能需要更改一些Ranks 或交换两个Ranks 所以。

另一方面,我必须在 UPDATEDeleteInsert Triggers 中进行操作,否则你会推荐。

  1. 是否有identity(1,1)等机制或其他内置 SQL Server 中的服务旨在解决此问题?
  2. 如果否,在性能方面的最佳方法是什么 操作?(答案应该有一个很好的解释 实施地点(触发器或...),索引问题,也可能 需要更改我的表定义)

谢谢。

【问题讨论】:

  • 您的排名是基于其他可以让您重新计算的吗?如果没有,您可能只需要进行更新。看不到触发器如何在这方面为您提供帮助。
  • @JamesZ,不。排名的概念完全是唯一的,它仅取决于没有任何其他数据的人可以从中产生排名。更新应该在触发器中,因为我希望能够保证顺序或排名。

标签: sql-server database


【解决方案1】:

如果您的表中有RankRank 行从1N,并且您插入一个带有Rank=2 的新行,那么您将不得不UPDATE(即更改)值N-2 行。您必须对表进行大量更改。恐怕没有什么神奇的方法可以加快速度。

如果你真的要更新Rank,那就是。

但是,也许,您真的需要将Rank 作为一个没有间隙的整数。

Rank 的真正目的是定义一定的行顺序。要定义顺序,您需要知道每一行之后是哪一行。因此,当用户说他想添加Sahar 和排名2 时,这实际上意味着Sahar 应该在Ali 之后,但在Sara 之前,因此可以将新行的排名设置为,比如说(1+2)/2 = 1.5

因此,如果您将 Rank 设为浮点数,您将能够在表格中间插入新行,而不会更改所有其他行的 Rank 的值。

如果您想将Rank 呈现给用户作为一个没有间隙的整数序列,请使用类似:

ROW_NUMBER() OVER(ORDER BY FloatRank) AS IntegerRankWithoutGaps

此外,如果您删除了一行,您也不需要更新表的所有行。持久化的FloatRank 值会有间隙,但在应用ROW_NUMBER 时会消失。

从技术上讲,您不能无限期地将 8 字节浮点间隔分成两半,因此您应该偶尔运行一个维护过程,以“规范化”您的浮点等级并更新表中的所有行。但是,至少这个代价高昂的过程可以不经常运行并且在系统负载最小的情况下运行。

此外,您可以从浮点值开始,而不是 1,而是进一步分开。例如,不要以1000, 2000, 3000, 4000, ... 开头,而不是1, 2, 3, 4...

【讨论】:

  • 我投票给你的答案是因为减少了Delete(和任何操作)的运营成本。总之,您的方法的主要优点是数据操作成本较低。但是由于等级标准化(第一个问题),它会导致数据读取成本增加。如果我们不规范化,那么排名数字可能会有差距,并且在我们的 UI 阶段(第二个问题)会很糟糕,无论如何我会接受你的答案,但可能需要等待一段时间才能获得更好的答案!谢谢。
  • 在一般情况下,在插入和删除数据时保持排名数字没有间隙可能非常昂贵,因为您必须确保没有两个不同的事务更新同时表。使用ROW_NUMBER 是一种权衡,但它应该相对便宜,尤其是当您在基础列上有索引时。如果有索引,ROW_NUMBER 就不必进行排序。
  • 其实这一切都取决于插入/删除/更新和读取的频率。如果插入很少,但读取很多,则在插入数据时重新计算和更新排名可能会更好。您无法降低重新计算的成本,但可以延迟支付这笔费用。
【解决方案2】:

最简单和透明的方法是添加列,您将在其中定义表中的行序列,然后在该列上创建聚集索引。该索引将根据需要保留数据。

【讨论】:

  • 欢迎所有建议!:) ,这似乎是个好主意,但我需要查看有关您的解决方案的更多详细信息。
  • 你需要什么样的细节?
  • 我的意思是你在哪里保存Rank 我已经在我的问题中解释过?你如何处理这些差距?您如何声称您的方法在插入数据和读取数据方面具有更好的性能,受让人保留排名顺序而没有任何间隙?
  • 让我们区分两个术语:表中的序列和行排名。我相信您必须存储行序列/位置而不是排名并即时计算排名。如果您在插入/删除期间计算排名 - 由于性能原因,您的进程将在某一天停止。 RDBMS 不适合此类操作。
  • RDBMS 不适合此类操作”。那么你的建议是什么?
猜你喜欢
  • 2015-12-31
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多