我想了解一些关于mysql架构的事情。 1. sql如何处理索引表中的插入、删除、更新操作? 2.据说,当索引页不在缓冲池中时,仅在更改缓冲区中进行更改。因此,如果在缓冲池加载相关索引页后进行更改,那么它也必须更改磁盘中的同一页。正确的?那么一个手术必须在三个不同的地方进行吗? 3. NULL值如何索引?它们将存储在 b+tree 中的什么位置? 4.如果我们更新一条数据,它是聚集索引,那么它什么时候会在磁盘中更新呢? 5.批量加载时会发生什么?
最佳答案
如何处理插入/更新/删除...
- 获取(并缓存)定位要更新/删除的行或将插入新行的 block 所需的索引 block 。
- 获取数据 block 。请注意,所有索引都包含
PRIMARY KEY
,它与数据聚集在一起。 - 修改数据 block 以反射(reflect)更改。还要记住旧数据——以防最终发生
ROLLBACK
。 - 更新唯一索引 block (包括 PK)。
- 将非唯一索引更改存储在更改缓冲区中。 (正如您所指出的。)
更改缓冲区被设计为对实际索引 block “透明”。
- 无论条目是否在 CB 中,索引查找始终会“做正确的事情”。
- 将 CB 条目折叠回实际索引 block 是在“后台”和/或空间不足时完成的。 (我认为 CB 默认为 buffer_pool 的 1/4。)
- 事务日志中存储了足够的信息,这样崩溃就不会丢失待处理的索引更新。
- 显然,CB 是为了性能而发明的。索引更新可以被延迟,同时,比需要更新的索引 block (16KB)占用的空间要少得多(通常只有几十个字节)。多个更改(通常)可以应用于单个索引 block ——这是主要的节省。但需要注意的是,由于随机性,UUID、MD5等无法很好地利用CB。当前日期时间/时间戳的非唯一索引是 CB 缓冲真正发挥作用的情况。
(抱歉,对于您所询问的级别,我对 CB 的了解有点模糊。我建议您阅读代码。)
NULL
...我相信它被视为一个单独的值,在 B+Tree 中的所有非空值之前排序。但为了混淆这个问题,有一个标志确定空值是否被视为彼此相等。并且对 PRIMARY
/UNIQUE
键有限制。
与 NULL 相关...对 DATE
或 DATETIME
的某些变体/函数执行 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/