因为公司业务需要,有大搞10亿条左右的历史数据需要插入到sql server 中,插入脚本使用的是python。需要注意的是,数据中有重复的部分需要过滤掉。
尝试1:跟线上一样中规中举的插入。步骤类似下面:
- 解析数据
- 选择哪些被插入: select * from in ()
- insert into...
此时的插入非常慢,慢到不可接受,几乎需要一个月。
在分析了上面步骤的耗时之后,发现步骤1解析数据因为是本地操作所以比较稳定,耗时不大。步骤2的select占据了非常大的时间,在表中数据量达到千万级别之后,几乎占据了一个流程的大部分。
尝试2:将表中的已有数据读取到内存中,从而释放select操作。
- 解析数据
- 从内存中缓存的dict表中判断哪些被插入,哪些是已有的数据
- insert into
经过上面的改进之后,时间耗费大大减少,性能提升超过 60%。但是还是比较慢,于是去看看sql的优化。完了之后发现,因为在尝试1中需要select,因此对关键的列建了索引而且是聚集索引,好吧,难怪插入这么慢。
尝试3:将数据库的所有的聚集索引全部去掉,因为我们只有insert的操作,索引在入库的过程中没有任何用处。
- 关闭表的所有的聚集索引
- 解析数据
- insert into
- 重建索引
经过3之后,性能比2中提升了10倍。OK,看来在大批量更新的场景中,聚集索引真的不适合。