我有一张包含7000万条记录的表格,并且缺少一个索引。我想计算添加索引的时间,而不需要备份表并在备份表上执行索引。
我只是想知道它是慢两倍(线性)还是指数。
数据库:mysql 5.0
非常感谢
答案 0 :(得分:4)
(免责声明:我对MySQL的经验很少)
它应该介于两者之间。
整个操作的绝对最低的复杂性将是按顺序读取所有记录时出现的复杂性,这是一个线性过程 - O(n)
。这是一个I / O绑定操作,并没有太多可以做的事情 - 大多数操作系统中的现代缓存系统可能会有所帮助,但只能在正在使用的数据库中并且适合可用内存。
在大多数SQL引擎中,索引是B树的一些变体。将单个记录插入到这样的树中的CPU复杂度大致为O(log(n))
,其中n
是其大小。对于n
条记录,我们的复杂度为O(n log(n))
。操作的总复杂性应为O(n log(n))
。
当然,它并不那么简单。计算索引树并不是真的占用CPU,因为索引页应该适合任何现代系统的RAM,当树没有重新平衡时插入单个节点的操作将接近{{ 1}} time-wise:用于更新索引的叶页的单个磁盘操作。
然而,由于树确实被重新平衡,事情可能会更复杂一些。可能必须将多个索引页面提交到磁盘,从而增加了必要的时间。粗略猜测,我会说O(1)
是一个好的开始......
编辑:
我刚刚发现,70,000,000个B树条目实际上可能不适合内存缓存。它将在很大程度上取决于索引的。 O(n log(n))
列可能没问题,但INTEGER
列完全是另一个故事。如果平均字段长度为100字节(例如HTTP链接或非英语UTF-8文本的30个字符),则需要超过7GB的内存来存储索引。
底线:
如果索引适合缓存,那么由于构建索引应该是一个单独的DB事务,它将是I / O绑定的并且大致是线性的,因为所有记录都必须被解析然后索引itelse必须写入永久存储。
如果索引不适合缓存,则复杂性会增加,因为索引本身的I / O等待时间会参与每个操作。
答案 1 :(得分:1)
thkala描述的对于插入单个行是正确的,但是在创建新索引时,没有合理的RDBMS只会执行n
插入,而是直接从叶节点开始构造索引。这个过程几乎肯定会受到IO限制。
因此,实际上,重新索引时间应该是线性的:两倍于记录的两倍。