首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

向存在索引的表插入大数据有关问题

2013-11-20 
向存在索引的表插入大数据问题每月需向某表添加约800万条数据,并且该表还需查询及统计。由于客户对插入及统

向存在索引的表插入大数据问题
每月需向某表添加约800万条数据,并且该表还需查询及统计。
由于客户对插入及统计都有时间限制。
现在采取的方案包括
1.对该表按月份字段进行分区。(但分区后插入速度会更慢,但查询统计时应该会快些)
2.插入前删除所有索引(drop index ),插入后再创建索引create index。

但现在的问题时,随着插入的数据越来越多(虽然分区了),以后每次的drop index, create index
将会越来越慢吧?

我的想法是,能否只drop 、create某个分区上的索引(因为每月插入的数据,都肯定是往同一个区的)。

或者大家针对大量数据插入,有什么好的解决方案(要求是能尽快完成插入,当然因为表要做查询统计,不可能不建索引)。

谢谢!
[解决办法]

引用:
@yupeigu
如果不能先停用,只能组织好像就无法满足了。呵呵。


大伙对大数据的插入,都是先删索引,再建索引吗?


给你做了一个例子,其实就是,你导入数据,和当前的分区表没有关系。

首先,你再建立一个分区表,结构和原来的表是一样的,然后把新的一个月数据800w导入到这个临时建立的分区表中,

然后,导入后,要建立相应的索引,这个索引和原来的表一样,

最后,切换,也就是switch,就是把刚才导入的数据,所在的分区表的分区,switch到原来表的新分区中。当然,在swith之前,必须要split出一个新的分区,指定使用的下一个文件组是哪个:

基本上是秒级切换,对当前业务没有任何影响:


alter database wc
set single_user
with rollback immediate

drop database wc




--1.创建数据库  
create database wc  
on primary  
(  
    name = wc_data,  
    filename = 'D:\wc_data.mdf'  
)  
log on  
(  
    name = wc_log1,  
    filename = 'd:\wc_log1.ldf'    
),  
(  
    name = wc_log2,  
    filename = 'd:\wc_log2.ldf'  
)  
  
go


use wc
go

--4.创建分区函数,3个值,但是会有4个分区
create partition function wcLeftRange(char(6))  
as range left for values('201309','201310','201311')  


  
--5.创建分区方案,4个文件组  
create partition scheme wcLeftRangeScheme  
as partition wcLeftRange  
to ([primary],[primary],[primary],[primary])



--6.建表,聚集索引,插入数据
create table temp_UserBill
(
BusinessDate char(6), F1 varchar(100), F2 Varchar(100)
)

create clustered index idx_temp_UserBill on temp_UserBill(BusinessDate)


insert into temp_UserBill
select '201309','aa1','bb1' union all
select '201309','aa2','bb2' union all
select '201310','aa1','bb1' union all
select '201310','aa2','bb2' union all
select '201311','aa1','bb1' union all
select '201311','aa2','bb2' union all
select '201312','aa','bb' 

go


--7.要转化为分区表,必须要删除聚集索引
drop index idx_temp_UserBill on temp_UserBill


--8.然后再重新建立一个聚集索引,并且指定:分区方案和分区字段
create clustered index idx_temp_UserBill on temp_UserBill(BusinessDate)
on wcLeftRangeScheme(BusinessDate)  


--9.查询表中的数据,是在那个分区里
select *,  
  
       --$partition函数,后面是分区函数名称,列名称,显示了这条数据是在第几个分区 
       $partition.wcLeftRange(BusinessDate) as partition   
from temp_UserBill 
/*
BusinessDateF1F2partition
201309        aa1bb11
201309        aa2bb21
201310        aa1bb12
201310        aa2bb22
201311        aa1bb13
201311        aa2bb23
201312        aabb4
*/





--10.1指定下一个要使用的分区文件组  
alter partition scheme wcLeftRangeScheme  
next used [primary]  
  
--10.2定义一个新的边界值来创建一个新的分区  
alter partition function wcLeftRange()  
split range ('201312')  
  
  
  
  
--11.新建一个表,你把800w数据,导入到这个表  
create table Import_UserBill
(
BusinessDate char(6), F1 varchar(100), F2 Varchar(100)
)on wcLeftRangeScheme(BusinessDate)   


insert into Import_UserBill
select '201401','aa1','bb1' union all
select '201401','aa2','bb2'


--上面先导入数据,再建立索引,速度会更快  
create clustered index idx_Import_UserBill on Import_UserBill(BusinessDate)
on  wcLeftRangeScheme(BusinessDate)
  
  
  
       
--12.把源表的第2个分区转到目标表  
--要求:源表和目标表必须在同一个文件组上,且目标表必须为空  


--当然,目标表也可以是分区表,也必须为空,且在同一个文件组上  
alter table Import_UserBill   
SWITCH partition 5  to dbo.temp_UserBill partition 5


--13.
select *,
 --$partition函数,后面是分区函数名称,列名称,显示了这条数据是在第几个分区 
       $partition.wcLeftRange(BusinessDate) as partition 
from temp_UserBill
/*
BusinessDateF1F2partition
201309aa1bb11
201309aa2bb21
201310aa1bb12
201310aa2bb22
201311aa1bb13
201311aa2bb23
201312aabb4
201401aa1bb15
201401aa2bb25
*/

热点排行