【问题标题】:MySQL: Optimizing UPDATE of many rows in a large tableMySQL:优化大表中多行的更新
【发布时间】:2011-02-02 09:27:11
【问题描述】:

表格是使用nested set model 组织的。当我插入一些东西时,我需要将所有具有左/右值 > 目标的东西移到左边。

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

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

  • 对表格的物理布局进行规范化/碎片整理/重新排序?
  • 创建更好的索引?
  • 更聪明地避免问题?

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

【问题讨论】:

    标签: sql mysql optimization innodb


    【解决方案1】:

    没有灵丹妙药,但有一些想法......

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

    虽然索引可以加快查询速度,但索引过多会减慢更新速度,因为索引需要反映数据中的更新。请注意,您的left 索引实际上是无关紧要的,因为它是left/right 索引上的前导字段。话虽如此,由于您可能通常会使用范围查询,因此 left 和 right 上的索引可能就足够了(也就是说,我可能倾向于删除 left/right 索引,除非您知道 它正在被使用)。松散地说,如果前面的所有列都在 equality 引用中使用,MySQL 只能使用后面的复合索引。

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

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

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

    【讨论】:

    • 很好的答案。我会去拿 2 升咖啡,然后思考一下这有什么帮助:)
    【解决方案2】:

    在其他条件相同的情况下,使用 ENGINE=MEMORY 创建一个重复的临时表应该会加快您的更新速度。

    【讨论】:

    • 使用临时表观察tmp_table_size和max_heap_table_size时要小心。您的表格大小必须小于或等于这两个变量中的较小者,这对于大型表格来说可能是个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 2017-12-30
    • 2020-09-08
    • 1970-01-01
    相关资源
    最近更新 更多