【问题标题】:What happens during the insertion, deletion and update in sql?sql中的插入、删除和更新过程中会发生什么?
【发布时间】:2017-07-11 02:03:42
【问题描述】:

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

【问题讨论】:

  • 如果这个问题只是关于mysql,为什么sql-server 标签?
  • 这些都是相当多的问题。由于需要的内容太多,有些人可能会辞职写答案。您还需要有信心回答每个方面的问题。为什么不将主题组织和拆分为不同的问题?

标签: mysql indexing innodb b-tree


【解决方案1】:

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

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

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

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

(对不起,我对CB的了解对于你所问的水平有点模糊,建议你阅读代码。)

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

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

集群 UNIQUE 索引...所有(?)写操作必须检查所有唯一索引,因此CB不参与此类。注意:在 InnoDB 中,PRIMARY KEY 始终是集群且唯一的,不能(?)拥有NULLs

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

奖励答案...

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

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

【讨论】:

  • 感谢您花时间回答问题。你能建议我在哪里可以了解更多关于这些内部事物的信息吗? @里克詹姆斯
  • Percona.com 的博客内容很多。我认为 Jeremy Cole 在 CB 上有一个博客。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
相关资源
最近更新 更多