我正在交换同一个表中的两个相邻列值。我觉得我这样做的方式可以在不需要交易的情况下进行优化,但我还没有设法减少它。
START TRANSACTION;
UPDATE comparisons
SET comparisons.position = (@pos := comparisons.position - 1)
WHERE comparisons.id = ? LIMIT 1;
UPDATE comparisons
SET comparisons.position = (@pos + 1)
WHERE comparisons.position = @pos
AND comparisons.id <> ?;
COMMIT;
有没有人有这类问题的经验并设法提出更有效的解决方案?
答案 0 :(得分:2)
没有足够的信息可以确定,但如果该查询很慢(我不是说它),那么第一个罪魁祸首是{{1}没有索引。这将使第二个UPDATE中的comparisons.position
对于大型表来说非常慢。请查看EXPLAIN UPDATE ...
。
WHERE comparisons.position = @pos
不会成为问题,因为结果已受comparisons.id <> ?
约束。
否则,交易通常不是性能问题的根源。我确信有人可以在一个单一的原子声明中提出一个复杂的方法,但它可能会更快。
至于优化算法,看起来您正在交换列表中的元素位置。一些事情会使这更高效。
comparisons.position = @pos
编入索引。comparisons.position
唯一。使comparisons.position
唯一保证不存在重复......但它确实使算法复杂化。我会继续努力。
There's already an answer for swapping two rows' values,但MySQL不允许您在同一个表格上进行子选择,因为它不会更新,因此它无法正常工作。
允许通用位置交换意味着如果要将元素移动到多个位置,则可以在一组查询中进行,而不是N次查询。
使其成为存储过程具有封装的所有好处,处理数据的所有内容都使用相同的功能。该功能可以在以后更改其功能。写一个带id和移动它的位置数,另一个带两个id来交换。
答案 1 :(得分:0)
一旦你有@pos,这将在一个语句中执行两个UPDATE:
UPDATE tbl
SET pos = @pos+@pos+1 - pos
WHERE pos IN (@pos, @pos+1);