如何优化此MySQL事务?

时间:2015-03-29 18:40:26

标签: mysql

我正在交换同一个表中的两个相邻列值。我觉得我这样做的方式可以在不需要交易的情况下进行优化,但我还没有设法减少它。

 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;

有没有人有这类问题的经验并设法提出更有效的解决方案?

2 个答案:

答案 0 :(得分:2)

没有足够的信息可以确定,但如果该查询很慢(我不是说它),那么第一个罪魁祸首是{{1}没有索引。这将使第二个UPDATE中的comparisons.position对于大型表来说非常慢。请查看EXPLAIN UPDATE ...

WHERE comparisons.position = @pos不会成为问题,因为结果已受comparisons.id <> ?约束。

否则,交易通常不是性能问题的根源。我确信有人可以在一个单一的原子声明中提出一个复杂的方法,但它可能会更快。

至于优化算法,看起来您正在交换列表中的元素位置。一些事情会使这更高效。

  • 确保已将comparisons.position = @pos编入索引。
  • 使comparisons.position唯一。
  • 允许进行通用位置交换,而不仅仅是+1和-1。
  • 编写存储过程。

使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);