MySQL:优化大表中许多行的UPDATE

时间:2011-01-17 14:38:11

标签: sql mysql optimization innodb

该表使用nested set model进行组织。当我插入一些东西时,我需要用左/右值移动所有内容>目的地在左边。

UPDATE projects SET rgt = rgt + 2 WHERE rgt >= @superRgt;

此查询可能需要几秒钟才能完成,这是不可接受的。我的问题是;如何优化此查询? 有可能......

  • 规范化/整理/重新排序表的物理布局?
  • 创建更好的索引?
  • 只是更聪明,避免问题?

我们正在使用Innodb表,并且左侧,右侧和左侧/右侧已经有索引。该表有大约100k行。

2 个答案:

答案 0 :(得分:1)

没有神奇的子弹,但有些想法......

我知道它提出了很多,我从未见过表的物理布局会改变真实工作负载的MySQL性能(具有任何意义)。

虽然索引可以加速查询,但由于索引需要反映数据中的更新,因此索引过多会降低更新速度。请注意,您的left索引实际上是无关紧要的,因为它是left/right索引上的主要字段。话虽如此,由于您可能通常会使用范围查询,leftright上的索引可能就足够了(也就是说,我可能倾向于删除left/right索引,除非你知道它被使用了)。简而言之,如果在相等引用中使用了所有前面的列,MySQL只能使用复合索引的后半部分。

无论如何,为了加快查询的执行速度,您的左/右字段是否有可能呈现负值?如果是这种情况,那么您可以将数据“移动”到左侧右侧的枢轴点的较小一侧 - 以较小的行数更新为准。

请注意,如果您要更新太多行,MySQL根本不会使用索引。表行的百分比有一个启发式阈值(通常报告为~30%),之后MySQL将拒绝使用索引。也就是说,在某一点上,最好是进行一次磁盘搜索并扫描整个表,而不是对表中行的> 30%执行磁盘搜索。

回到基础,你偏离了(差)默认的innodb配置设置吗?有关指示,请参阅this article。至少,确保您的数据集适合innodb_buffer_pool_size(如果您有RAM),如果您的应用程序允许,请将innodb_flush_log_at_trx_commit更改为0或2。

答案 1 :(得分:0)

所有其他方法相同,使用ENGINE = MEMORY创建重复的临时表应加快更新速度。