mysql - sql中插入、删除、更新时会发生什么?

标签 mysql indexing innodb b-tree

我想了解一些关于mysql架构的事情。 1. sql如何处理索引表中的插入、删除、更新操作? 2.据说,当索引页不在缓冲池中时,仅在更改缓冲区中进行更改。因此,如果在缓冲池加载相关索引页后进行更改,那么它也必须更改磁盘中的同一页。正确的?那么一个手术必须在三个不同的地方进行吗? 3. NULL值如何索引?它们将存储在 b+tree 中的什么位置? 4.如果我们更新一条数据,它是聚集索引,那么它什么时候会在磁盘中更新呢? 5.批量加载时会发生什么?

最佳答案

如何处理插入/更新/删除...

  1. 获取(并缓存)定位要更新/删除的行或将插入新行的 block 所需的索引 block 。
  2. 获取数据 block 。请注意,所有索引都包含PRIMARY KEY,它与数据聚集在一起。
  3. 修改数据 block 以反射(reflect)更改。还要记住旧数据——以防最终发生ROLLBACK
  4. 更新唯一索引 block (包括 PK)。
  5. 将非唯一索引更改存储在更改缓冲区中。 (正如您所指出的。)

更改缓冲区被设计为对实际索引 block “透明”。

  • 无论条目是否在 CB 中,索引查找始终会“做正确的事情”。
  • 将 CB 条目折叠回实际索引 block 是在“后台”和/或空间不足时完成的。 (我认为 CB 默认为 buffer_pool 的 1/4。)
  • 事务日志中存储了足够的信息,这样崩溃就不会丢失待处理的索引更新。
  • 显然,CB 是为了性能而发明的。索引更新可以被延迟,同时,比需要更新的索引 block (16KB)占用的空间要少得多(通常只有几十个字节)。多个更改(通常)可以应用于单个索引 block ——这是主要的节省。但需要注意的是,由于随机性,UUID、MD5等无法很好地利用CB。当前日期时间/时间戳的非唯一索引是 CB 缓冲真正发挥作用的情况。

(抱歉,对于您所询问的级别,我对 CB 的了解有点模糊。我建议您阅读代码。)

NULL...我相信它被视为一个单独的值,在 B+Tree 中的所有非空值之前排序。但为了混淆这个问题,有一个标志确定空值是否被视为彼此相等。并且对 PRIMARY/UNIQUE 键有限制。

与 NULL 相关...对 DATEDATETIME 的某些变体/函数执行 PARTITION BY RANGE 时,无效日期会变成NULL,显式存储在“第一个”分区中。新手常常会感到困惑,为什么分区修剪似乎不起作用。 (推荐的部分解决方法:有一个“第一个”分区,否则为空。)

聚集 UNIQUE索引...所有(?)写入操作必须检查所有唯一索引,因此CB不涉及这样的。注意:在 InnoDB 中,PRIMARY KEY 始终是集群且唯一的,并且不能(?)有 NULL

批量加载...我发现 100 行 INSERT 的运行速度是 100 个单独 INSERT 的运行速度的 10 倍。 (这是由于解析等原因)但在低级别上,批量插入或加载数据只是一堆单独的插入。因此,上述讨论适用。

奖励答案...

“IODKU”(INSERT ... ON DUPLICATE KEY UPDATE)几乎遵循上面的 1..5 步骤。在定位要更新的行时,它会发现是更新还是插入,然后相应地继续。

REPLACE 实际上是 DELETE 加上 UPDATE 的简写。但请注意这个异常...如果表中有两个唯一键,则单行 REPLACE 可能会在插入 1 行之前删除 2 行。

关于mysql - sql中插入、删除、更新时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42367493/

相关文章:

mysql - 按相关表列排序表的最快方法

java - 使用 MongoDb 创建索引

MySQL静态表的最佳索引

mysql - 没有主键的连接表

MySQL 查询在列中的每个值之前插入一个 x

java - 可以在android上使用jdbc驱动吗?

mysql - 关于 sphinx 段规则

java - 如何获取网格 Pane 内的信息(javaFX)

Python - 根据列表位置匹配对象

php - 交易未完成