用于在数据库表中建立索引的数据结构是B-Tree(默认值,在B-Tree,R-Tree和Hash中)。由于查找,删除和插入操作都可以在B树中以对数时间完成,那么为什么只从索引表中读取速度更快,而写入速度却较慢呢?
答案 0 :(得分:3)
索引仅用于加速SELECT
语句。对于INSERT
,UPDATE
和DELETE
,由于索引需要作为语句的一部分进行更新,因此您的语句将比正常情况慢。
我也许应该澄清UPDATE
/ DELETE
的要点。的确,由于增加了开销的索引的变化,这些语句的速度会变慢,但是WHERE
和UPDATE
语句的初始查找部分(DELETE
)可能是由于索引加快了。基本上,在任何使用WHERE
子句的地方,只要您引用了索引字段,该语句的记录选择部分都应该有所增加。
此外,如果UPDATE
语句未更改属于索引的任何列,那么由于索引未更新,因此您不应看到任何其他慢速情况。
答案 1 :(得分:1)
因为索引需要额外的磁盘空间。索引增加需要记录和写入数据库的数据量。索引降低写入性能。当索引覆盖的列被更新时,该索引也必须被更新。同样,任何删除或插入操作都需要更新相关索引。
索引的磁盘空间和写入代价正是为什么创建索引时需要格外小心。
也就是说,使用索引可以改善对未索引列的更新。
此:
UPDATE Table SET NonIndexedColumn = 'Value' WHERE IndexedKey = 'KeyValue'
比这更快:
UPDATE Table SET IndexedColumn = 'Value' WHERE IndexedKey = 'KeyValue'
但是在任何大小合理的表中,以上两个可能都比这要快:
UPDATE Table SET NonIndexedColumn = 'Value' WHERE NonIndexedKey = 'KeyValue'
即使表和索引需要更新,删除(尤其是单个删除)也可以更快。这仅仅是因为查询引擎可以更快地找到目标行。也就是说,读取索引,查找行,删除行并更新索引可能更快,而不是扫描整个表以查找正确的行并删除相关的行。但是,即使在这种情况下,也将要写入更多数据。只是与索引相比,扫描整个表的IO成本可能会很高。
最后,从理论上讲,将插入内容分布在多个磁盘页面上的集群密钥可以使系统支持更多的 concurrent 插入内容,因为插入内容通常需要页面锁才能起作用,但这是一种不常见的情况并可能由于使聚集索引碎片化而导致读取性能变差。
答案 2 :(得分:0)
INSERT
和DELETE
必须更新表的每个索引(如果没有聚集索引,则更新堆),以保持一致性。 UPDATE
可能不愿更新较少的索引,具体取决于更新所影响的列(因为只有那些索引/包括那些列的索引才需要更新)
另一方面,SELECT
仅在读取,因此,如果索引包含SELECT
所需的所有列,则只需访问 索引。我们知道该索引中的数据准确是准确的,因为需要进行修改操作才能保持该一致性。