简介:索引损坏的表XSDTM129.RT是个历史数据表,该表数据是在实时插入的,所以表内数据量巨大,多达6亿多条,而由于索引损坏,无法先进行数据的删除,而传统的删索引—重建索引的时间消耗非常大,所以考虑能否用重建RT表来代替原表,并把需要所需数据导入新RT表,删除旧表的方式来提高索引损坏修复的效率。
注:由于此次操作的表数据是实时插入的,而此法在执行过程中需要将数据库设为单用户模式,所以在执行换表的那段时间内的数据会存在丢失的情况,所以采用此法时要慎重!!!


(该方案在生产服务器已经实施,保留数据1500000条,语句执行3分钟,后续等采集程序采数到正常数据存入数据库大约几分钟~)


 


具体方案:把XSDTM129.RT表重命名为XSDTM129.MT---新建XSDTM129.RT表(注意:同一架构下不能有同名索引及主键)---将需要的数据导入到新的RT表。


 


为测试方案是否可行,先在测试服务器上做如下实验。


环境:测试服务器上一命名实例,XSDTM129.RT表,数据量约为3亿。


我写了一个萌萌哒的小存储过程用于测试更换表名对存储过程往表查数据的影响,并手动向XSDTM129.RT表插入数据。





索引已损坏 索引数据库损毁_sql server



然后将XSDTM129.RT更名为XSDTM129.MT。


EXEC sp_rename 'XSDTM129.RT' , 'MT'


 


创建RT表



索引已损坏 索引数据库损毁_数据_02



再次手动执行往RT插数据的存储过程,为保证正确性,手动插入了两次。并选出结果。



索引已损坏 索引数据库损毁_sql server_03



 


由上图可以看出,数据全部插入了新的RT表。


同理测试了视图,选出的是新RT表里的数据。


 


由此基本可以判断更换表名对存储过程和视图的影响是没有的!


 


接下来就是如何把需要的数据导入到新表,由于RT表数据是每隔几秒都会有插入,哪怕三天的数据量都达到一百多万,所以考虑插入的时候,查询的判断条件用record_id(该表在record_id列上建有索引)。


INSERT INTO xsdtm129.rt
       (ts_id ,
          class_num ,
          ord_class ,
          team_set ,
          class_start_server ,
          class_end_server ,
          record_timestamp ,
          runtime_s ,
          article_id ,
          current_class_output ,
          total_output ,
          total_output_c ,
          a_output ,
          b_output ,
          c_output ,
          d_output ,
          a_total ,
          b_total ,
          c_total ,
d_total ,current_length ,fixed_length ,rolla_v ,spindle_v ,twist_ratio ,class_num_plc ,Dev_GUID ,i_signal ,q_signal ,sec_A_length ,sec_B_length ,sec_C_length ,sec_D_length ,sec_A_change_amount ,sec_B_change_amount ,sec_C_change_amount ,sec_D_change_amount ,run_efc ,device_state ,Article_GUID ,a_total_calc ,b_total_calc ,c_total_calc ,d_total_calc , row_interval ,statecode ,machineNo)
   SELECT ts_id ,
          class_num ,
          ord_class ,
          team_set ,
          class_start_server ,
          class_end_server ,
          record_timestamp ,
          runtime_s ,
          article_id ,
          current_class_output ,
          total_output ,
          total_output_c ,
          a_output ,
          b_output ,
          c_output ,
          d_output ,
          a_total ,
          b_total ,
          c_total ,
d_total ,current_length ,fixed_length ,rolla_v ,spindle_v ,twist_ratio ,class_num_plc ,Dev_GUID ,i_signal ,q_signal ,sec_A_length ,sec_B_length ,sec_C_length ,sec_D_length ,sec_A_change_amount ,sec_B_change_amount ,sec_C_change_amount ,sec_D_change_amount ,run_efc ,device_state ,Article_GUID ,a_total_calc ,b_total_calc ,c_total_calc ,d_total_calc , row_interval ,statecode ,machineNo
  FROM XSDTM129.mt WHERE record_id>614217880


 


Attention!!


为保证过程实施的稳定性,最好用以下 脚本 杀掉进程 、 把数据库切换为单用户模式,可以先把采集程序关了,等全部执行完后再次打开。如果整体执行报错的话,可以手动的一段一段的执行。


详情请见脚本!!


--杀掉进程
USE master
GO
DECLARE @kill varchar(max) = '';
SELECT @kill = @kill + 'KILL ' + CONVERT(varchar(10), spid) + '; '
FROM master..sysprocesses
WHERE spid > 50 AND dbid = DB_ID('A') --A为数据库名
PRINT @kill
EXEC(@kill);
 
GO
SET DEADLOCK_PRIORITY HIGH

USE A   --A为数据库名
GO
--更换表名
ALTER DATABASE A SET  SINGLE_USER;
GO
--更换表名
EXEC sp_rename 'XSDTM129.RT', 'MT';
GO
 
--新建XSDTM.RT表代替原表
CREATE TABLE [XSDTM129].[RT]
    (
      [record_id] [BIGINT] IDENTITY(1, 1) NOT NULL ,
      [ts_id] [INT] NULL ,
      [class_num] [TINYINT] NULL ,
      [ord_class] [NCHAR](1) NULL ,
      [team_set] [NCHAR](1) NULL ,
      [class_start_server] [DATETIME] NULL ,
      [class_end_server] [DATETIME] NULL ,
      [record_timestamp] [DATETIME] NOT NULL ,
      [runtime_s] [INT] NULL ,
      [article_id] [INT] NULL ,
      [current_class_output] [INT] NULL ,
      [total_output] [INT] NULL ,
      [total_output_c] [BIGINT] NULL ,
      [a_output] [INT] NULL ,
      [b_output] [INT] NULL ,
      [c_output] [INT] NULL ,
      [d_output] [INT] NULL ,
      [a_total] [INT] NULL ,
      [b_total] [INT] NULL ,
      [c_total] [INT] NULL ,
      [d_total] [INT] NULL ,
      [current_length] [INT] NULL ,
      [fixed_length] [INT] NULL ,
      [rolla_v] [DECIMAL](9, 2) NULL ,
      [spindle_v] [INT] NULL ,
      [twist_ratio] [INT] NULL ,
      [class_num_plc] [INT] NULL ,
      [Dev_GUID] [UNIQUEIDENTIFIER] NOT NULL ,
      [i_signal] [INT] NULL ,
      [q_signal] [INT] NULL ,
      [sec_A_length] [INT] NULL ,
      [sec_B_length] [INT] NULL ,
      [sec_C_length] [INT] NULL ,
      [sec_D_length] [INT] NULL ,
      [sec_A_change_amount] [INT] NULL ,
      [sec_B_change_amount] [INT] NULL ,
      [sec_C_change_amount] [INT] NULL ,
      [sec_D_change_amount] [INT] NULL ,
      [run_efc] [DECIMAL](5, 2) NULL ,
      [device_state] [INT] NULL ,
      [Article_GUID] [UNIQUEIDENTIFIER] NULL ,
      [a_total_calc] [INT] NULL ,
      [b_total_calc] [INT] NULL ,
      [c_total_calc] [INT] NULL ,
      [d_total_calc] [INT] NULL ,
      [row_interval] [INT] NULL ,
      [statecode] [TINYINT] NULL ,
      [machineNo] [INT] NULL ,
      [article_name] [NVARCHAR](32) NULL ,
      CONSTRAINT [PK_RT_RecordID] PRIMARY KEY NONCLUSTERED ( [record_id] ASC )
        WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
               ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
    )
ON  [PRIMARY];
 
GO
 
ALTER TABLE [XSDTM129].[RT] ADD  CONSTRAINT [DF_RT_record_timestamp]  DEFAULT (GETDATE()) FOR [record_timestamp];
GO
 
ALTER TABLE [XSDTM129].[RT] ADD  CONSTRAINT [DF_RT_runtime_s]  DEFAULT ((0)) FOR [runtime_s];
GO
 
 
--为表建索引,在以下空白处可加上添加索引的代码






SET IDENTITY_INSERT XSDTM129.RT ON;   
GO 
 
BEGIN TRAN;
 
INSERT  INTO XSDTM129.RT
        ( record_id ,
          ts_id ,
          class_num ,
          ord_class ,
          team_set ,
          class_start_server ,
          class_end_server ,
          record_timestamp ,
          runtime_s ,
          article_id ,
          current_class_output ,
          total_output ,
          total_output_c ,
          a_output ,
          b_output ,
          c_output ,
          d_output ,
          a_total ,
          b_total ,
          c_total ,
          d_total ,
          current_length ,
          fixed_length ,
          rolla_v ,
          spindle_v ,
          twist_ratio ,
          class_num_plc ,
          Dev_GUID ,
          i_signal ,
          q_signal ,
          sec_A_length ,
          sec_B_length ,
          sec_C_length ,
          sec_D_length ,
          sec_A_change_amount ,
          sec_B_change_amount ,
          sec_C_change_amount ,
          sec_D_change_amount ,
          run_efc ,
          device_state ,
          Article_GUID ,
          a_total_calc ,
          b_total_calc ,
          c_total_calc ,
          d_total_calc ,
          row_interval ,
          statecode ,
          machineNo ,
          article_name
        )
        SELECT  record_id ,
                ts_id ,
                class_num ,
                ord_class ,
                team_set ,
                class_start_server ,
                class_end_server ,
                record_timestamp ,
                runtime_s ,
                article_id ,
                current_class_output ,
                total_output ,
                total_output_c ,
                a_output ,
                b_output ,
                c_output ,
                d_output ,
                a_total ,
                b_total ,
                c_total ,
                d_total ,
                current_length ,
                fixed_length ,
                rolla_v ,
                spindle_v ,
                twist_ratio ,
                class_num_plc ,
                Dev_GUID ,
                i_signal ,
                q_signal ,
                sec_A_length ,
                sec_B_length ,
                sec_C_length ,
                sec_D_length ,
                sec_A_change_amount ,
                sec_B_change_amount ,
                sec_C_change_amount ,
                sec_D_change_amount ,
                run_efc ,
                device_state ,
                Article_GUID ,
                a_total_calc ,
                b_total_calc ,
                c_total_calc ,
                d_total_calc ,
                row_interval ,
                statecode ,
                machineNo ,
                article_name
        FROM    XSDTM129.mt(NOLOCK)
   WHERE   record_id > 1799926237 --order by record_id;--我想着用先查出一个record_id值,然后查询条件用这个会快些,因为该值是索引列。
 
COMMIT TRAN;
 
SET IDENTITY_INSERT XSDTM129.RT OFF; 
GO

ALTER database A SET MULTI_USER --切换回多用户模式
GO