假设我有一张结构如下的表:
id (int[11]), name(VARCHAR[255])
name
列有一个b树索引。
让我们假设按此顺序对此表进行查询:
现在,我知道在索引表中插入新行时,需要更新索引。这需要时间。但我的问题是:
谢谢。
更新
假设插入尚未在SELECT查询发出时更新索引。
答案 0 :(得分:2)
我认为这里有一些很好的信息: https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html
和: https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-structure.html
但一般来说,Insert会锁定行,但不会阻止Select(甚至不是新的Insert)。依赖于索引的Select查询由于新的Insert而当前正在构建,在构建索引之前不会“看到”新行。
每个Insert操作=将数据插入行+更改受影响的索引。 插入过程越长,索引越多,后续SELECT查询找到新行所需的时间就越长。
如果您正在编写代码,那么您可以让Select等待Insert完成。
根据以下评论添加更正和改进
我并不是说语句执行时间更长,我的意思是如果你在时间A插入一行,并且需要5秒才能完成操作,那么选择查询将在A + 2秒运行看不到行,在A + 6秒运行的选择查询会看到该行。
更清楚 - 插入不会延迟Select,除非您将数据库配置为在Insert上有表锁,但在插入完成之前,您将看不到任何Select查询中的Insert。
答案 1 :(得分:0)
我意识到只有我问题的第一部分得到了明确回答,我在问题的第二部分找到了一个明确的答案 - 第二次INSERT会发生什么?是否会等待索引从以前的INSERT完全更新? - 在批准的答案提供的link中。
在插入行之前,有一种称为插入的间隙锁 意图间隙锁定设置。此锁定表示插入的意图 这样一种方式,多个事务插入到同一个索引中 如果它们没有插入相同的间隙,则不必等待彼此 在差距内的位置。
这是它的总和,但为了深刻理解我建议在引用后阅读整篇文章。
再次,非常感谢您的批准答案。
答案 2 :(得分:-1)
在表中插入行只会在每个二级索引中插入一个新条目。事实证明,插入数据并在索引中插入新条目实际上是相同的操作 - 两者都向下钻取BTree(数据由PRIMARY KEY
列组织,二级索引由二级密钥列。)
INSERT
和任何索引更新都是原子的。也就是说,该条目同时被添加到索引中(就任何SQL 而言)是插入的行。
在幕后(在InnoDB中),有一个“更改缓冲区”,它会延迟实际将索引更新写入磁盘。但即使是电源故障也不会违反数据+索引更新的“原子”性质。
事务隔离模式可以让您在包含INSERT
的“事务”之前看到(或阻止您查看)记录。但这是一个不同的原子性水平。它与索引无关。