现在有一系统,数据库中的其中几个表会被很频繁地INSERT,有几个表会被很频繁地UPDATE和INSERT,
这些表的数据量非常大(INSERT的表每秒有几千条记录,UPDATE和INSERT的表每秒的记录稍小一点),
我现在采用的办法是,做INSERT的表没有建索引,是按天分区且只保留最近15天的记录,做UPDATE和INSERT的表建有索引(个数为1-4个),每天用作业将表的数据SWITCH到另一个分区表中。我的难题是:建有索引的表,每10多分钟就会产生15%-90%不等的索引碎片,这会导致WEB查询超时和写数据超时,不建索引又不行,因为在做UPDATE时,会先SELECT,然后做判断,有则UPDATE,无则INSERT。邹兄和大家有没有遇到类似的情况?有没有什么好的解决办法?为什么会有这么频繁的索引碎片?

解决方案 »

  1.   

    INSERT的表每秒有几千条记录?个人认为sql server做不到.
      

  2.   

    如果楼主能使用2005企业版的话,可以使用它联机建索引的功能(只有企业版有这个功能)。
    大概原理就是SQL会保持现有一组索引,同时并行再建第二组索引,等第二组索引建好之后,自动把第一组索引换掉。
    这个过程中整个数据库一直是可用的。如果不能使用2005企业版的话,另外,还有一个办法是使用 DBCC INDEXDEFRAG,
    这个命令是2000和2005的其他版本里面唯一能在线清除索引碎片的命令。
    使用这个命令时,表还是可访问的。
    但这个命令没有完全重建索引(DBCC DBREINDEX)那么彻底,它不能更新表的统计信息。LZ可以考虑试试 DBCC INDEXDEFRAG
      

  3.   

    我的数据库用的就是SQL SERVER2005,而我目前采用的对付索引碎片的办法就是做作业定期去Rebuild index,虽然这是联机操作,但我认为这不是解决问题的根本办法啊,而且我的作业定时居然要设置成20分钟才能完全对付索引碎片。大家还有没有从数据库的设计角度来解决这问题的办法呢?目前我用BLUK INSERT命令从txt文件中导入数据有时会超时,每次执行该命令的间隔是1个小时,这一个小时中,txt的文件大小达到30多M,而且是在应用层调用的该命令,大家看看是不是有什么解决办法呢?
      

  4.   

    调用数据前先删除索引,完成后Rebuild。不使用作业定期处理。
    感觉是你的结构流程设计肯定有问题。
      

  5.   

    我们现在也在做一个导大量数据的项目,实用ado.net做的先是webservice传送,之后批量插入
    20000条数据要1分钟插入时用sqlbulkcopy
    更新时先删除在插入
      

  6.   

    测试局域网内的,就是除去webservice时间上面的实用单条40000条大约2秒,除去其他因素单纯插入数据
      

  7.   

    选择空闲时间
    优化索引。。
    http://topic.csdn.net/u/20070329/17/38398e78-adac-4d7e-a8b6-f2d319d283e8.html
      

  8.   

    TUDOX去完成吧。还有,服务器搞台P560以上的啊,或者集群咯+磁盘柜
    就几千条数据而言,采用先放入缓存里,等数据量达到5万后在一次性INSERT进去,估计会好点。
      

  9.   

    我的难题是:建有索引的表,每10多分钟就会产生15%-90%不等的索引碎片,这会导致WEB查询超时和写数据超时,不建索引又不行,因为在做UPDATE时,会先SELECT,然后做判断,有则UPDATE,无则INSERT。 
    -----------------------------------------------------------------------
    可能还要仔细考虑一下每个索引的填充因子(fillfactor)的值,一般默认是90%,
    你可以试试减小这个值到80%甚至75%,看看会不会好一些,但索引文件的体积会增加一些。
      

  10.   

    我的难题是:建有索引的表,每10多分钟就会产生15%-90%不等的索引碎片,这会导致WEB查询超时和写数据超时,不建索引又不行,因为在做UPDATE时,会先SELECT,然后做判断,有则UPDATE,无则INSERT。 
    ----------------------------------------------------------------------------------------------------------------如果这个是 UPDATE 造成的, 则一般在设计上应该做一些调整
    从理论上来讲, UPDATE 导致索引碎片主要是由于被 UPDATE 的记录的索引页存储不下 UPDATE 的结果, 导致页拆分而产生碎片
    因此, 除了如楼上所说, 应该适当降低索引的 FILLFACTOR 外
    还应该考虑修改表结构, 为列预留空间
    例如, 如果你的某个列存储的数据在 0-50 个字符之间, 从节约空间的角度来考虑, 一般设置会采用 varchar/nvarchar
    但如果这个列被频繁更新, 则可能会经常导致页拆分(旧的数据比新的数据短)
    在这种情况下, 应该考虑将列设置为 char/nchar, 这样空间是定长的, 无论新旧数据的实际长度如何, 它都是标准的 50 字符, 这样能够大大避免页拆分, 从而达到减少索引碎片的目的(在一定程度上对更新速度也有提高, 因为更新数据页的时候, 也同时避免了数据页的拆分)
      

  11.   

    另外要考虑 CLUSTERED 索引(一般是主键) 的设计, 由于每个非 CLUSTERED 索引中都包含 CLUSTERED 索引的数据, 因此任何一个对 CLUSTERED 索引中的列的更新都会导致所有的非 CLUSTERED 索引被更新如果你的 UPDATE 经常有对 CLUSTERED 索引的更新, 则一般应该考虑更新 CLUSTERED 索引, 例如使用 标识列 这类列来做 CLUSTERED 索引.另外, 如果你的 CLUSTERED 索引的列长度较长, 一般也建议更换为使用 标识列 这类列来做 CLUSTERED 索引, 这样可以大大减少所有索引的存储空间, 这意味着 I/O 降低, 也就是索引检索效率提升
      

  12.   

    则一般应该考虑更新   CLUSTERED   索引
                 ^^^^^ 更换
      

  13.   

    考虑更新 CLUSTERED 索引,索引列的太长更换为标示列最主要的是看产生碎片的谁产生的,根据产生的操作,进行处理,未必一定在数据库级别上来处理这个问题,也可以考据一下,在业务流程上进行优化,缓冲业务数据等我用的sql server2005 暂时还没有碰到这样的问题,期待你的解决,以做后人借鉴,我顶!!!!!
      

  14.   

    非常感谢邹兄和大家的热心回复,我现在就准备按邹兄说的办法去调整,稍后我会附上结果。
    还有一个问题我也很奇怪,我的数据库中有一个表,我是按天分区的,共15个分区,此表我建了3个分区索引,而该表只进行BLUK INSERT操作,每次BLUK INSERT后,分区索引的碎片也非常大,而且15个分区的3个索引都有程度不等的碎片。这些碎片产生是不是和我上面的有些类似呢???
      

  15.   

    每次BLUK   INSERT后,分区索引的碎片也非常大,而且15个分区的3个索引都有程度不等的碎片。这些碎片产生是不是和我上面的有些类似呢???
    --------------------------------
    三种基本操作:insert,update, delete中
    INSERT和UPDATE都会造成索引碎片,
    而且INSERT造成碎片的可能性更大,
    UPDATE的字段如果没有在索引中则不会影响索引,
    DELETE基本不会,但会造成索引空间利用不足。