QunInfo群数据库的还原与优化

1、 背景sql

  这个数据库的数据文件mdf大概有8.5G左右,当还原数据库以后感受能够作不少性能方面上的调优,合并数据后mdf数据文件大概有6.2G左右,行压缩后mdf数据文件大概有4.8G左右,页压缩后mdf数据文件大概有4.5G左右,这里处于技术研究的目的,讲讲研究的成果分析,不用于商业目的;数据库

 

2、 优化项函数

咱们能够从下面3个不一样的方面来优化这两个数据库:性能

(一)对表进行分区;优化

(二)使用行压缩,压缩行数据;spa

(三)从新设计表结构,优化表空间;设计

 

3、 附加数据库code

1.先把11个QunInfo(群信息)数据库附加到数据库,下面的导入SQL语句在原来的基础上作了些修改:统一数据库名,这样作的好处就是后面作处理的时候方便按照顺序执行数据库;blog

--附加数据库
EXEC sp_attach_db "QunInfo01", "D:\DBBackup\QunData\QunInfo1_Data.MDF"
EXEC sp_attach_db "QunInfo02", "D:\DBBackup\QunData\QunInfo2_Data.MDF"
EXEC sp_attach_db "QunInfo03", "D:\DBBackup\QunData\QunInfo3_Data.MDF"
EXEC sp_attach_db "QunInfo04", "D:\DBBackup\QunData\QunInfo4_Data.MDF"
EXEC sp_attach_db "QunInfo05", "D:\DBBackup\QunData\QunInfo5_Data.MDF"
EXEC sp_attach_db "QunInfo06", "D:\DBBackup\QunData\QunInfo6_Data.MDF"
EXEC sp_attach_db "QunInfo07", "D:\DBBackup\QunData\QunInfo7_Data.MDF"
EXEC sp_attach_db "QunInfo08", "D:\DBBackup\QunData\QunInfo8_Data.MDF"
EXEC sp_attach_db "QunInfo09", "D:\DBBackup\QunData\QunInfo9_Data.MDF"
EXEC sp_attach_db "QunInfo10", "D:\DBBackup\QunData\QunInfo10_Data.MDF"
EXEC sp_attach_db "QunInfo11", 
"D:\DBBackup\QunData\QunInfo11_Data.MDF"

 

4、 合并数据库索引

2.修改各个数据库中表的名字:把QunList1统一修改成QunList01这样格式的,这样作的好处就是在合并数据的时候读取到的数据库的数据是按照顺序插入到表中的,不会形成数据页的拆分;

--格式化表名
USE QunInfo01
GO

exec sp_rename 'QunList1','QunList01'
exec sp_rename 'QunList2','QunList02'
exec sp_rename 'QunList3','QunList03'
exec sp_rename 'QunList4','QunList04'
exec sp_rename 'QunList5','QunList05'
exec sp_rename 'QunList6','QunList06'
exec sp_rename 'QunList7','QunList07'
exec sp_rename 'QunList8','QunList08'
exec sp_rename 'QunList9','QunList09'

 

3.建立一个名为QunInfo的数据库,设置数据库为简单恢复模式;

 

4.在QunInfo数据库中建立一个临时表:tables,用来保存全部的数据库与表的信息,提供数据库合并用;

--建立临时表
CREATE TABLE [QunInfo].[dbo].[tables](
    [db_name] [sysname] NULL,
    [table_name] [sysname] NULL,
    [status] [bit] default 0
) ON [PRIMARY]

--生成数据库名称与表名称的对应列表
EXEC sp_MSForEachDB 'USE [?];
    --插入表信息
    INSERT INTO [QunInfo].[dbo].[tables]([table_name])
        SELECT name from [?].sys.tables where name like ''QunList%'' order by name
    --更新数据库名称
    UPDATE [QunInfo].[dbo].[tables] SET [db_name] = ''?'' WHERE [db_name]

 

5、 优化数据库

5.通过评估,11个QunInfo数据库的QunList表数据的总和大概有9千万,QunList表中QunNum(群号)字段的最大值为100219998(能够经过QunInfo11数据库的QunList110表查询到:SELECT MAX(QunNum) FROM [QunInfo11].[dbo].[QunList110]),从业务的角度,可能须要查询某群的信息,因此这里就以QunNum做为分区,每1千万个群做为一个分区,这样计算那就须要11个文件组,若是你但愿和GroupData数据库的Group表对齐的话,也能够按照5百万个群做为一个分区;

 

6.下面是一个建立分区脚本的SQL脚本,执行下面的SQL会生成一个新的脚本,执行那个脚本就能够建立11个文件组、分区函数和分区方案;

--生成分区脚本
DECLARE @DataBaseName NVARCHAR(50)--数据库名称
DECLARE @TableName NVARCHAR(50)--表名称
DECLARE @ColumnName NVARCHAR(50)--字段名称
DECLARE @PartNumber INT--分区最大编号
DECLARE @PartNumberBegin INT--分区编号开始值
DECLARE @PartNumberBeginTemp INT--分区编号开始值临时值
DECLARE @PartNumberStr NVARCHAR(50)--分区值字符串
DECLARE @Location NVARCHAR(50)--保存分区文件的路径
DECLARE @Size NVARCHAR(50)--分区初始化大小
DECLARE @FileGrowth NVARCHAR(50)--分区文件增量
DECLARE @FunValue INT--分区分段值增量
DECLARE @FunValueBegin INT--分区分段值开始值
DECLARE @i INT--临时变量
DECLARE @sql NVARCHAR(max)

--设置下面变量
SET @DataBaseName = 'QunInfo'
SET @TableName = 'QunList'
SET @ColumnName = 'QunNum'
SET @PartNumber = 11
SET @PartNumberBegin = 1
SET @Location = 'D:\DBBackup\FG_QunList\'
SET @Size = '1024MB'
SET @FileGrowth = '1024MB'
SET @FunValueBegin = 10000000
SET @FunValue = 10000000

SET @sql = 'USE ['+@DataBaseName +']
GO'
PRINT @sql + CHAR(13)

--1.建立文件组
SET @i = 1
SET @PartNumberBeginTemp = @PartNumberBegin
PRINT '--1.建立文件组'
WHILE @i <= @PartNumber
BEGIN
    SET @PartNumberStr =  RIGHT('0' + CONVERT(NVARCHAR,@PartNumberBeginTemp),2)
    SET @sql = 'ALTER DATABASE ['+@DataBaseName +']
ADD FILEGROUP [FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+']'
    PRINT @sql + CHAR(13)
    SET @i=@i+1
    SET @PartNumberBeginTemp = @PartNumberBeginTemp+1
END

--2.建立文件
SET @i = 1
SET @PartNumberBeginTemp = @PartNumberBegin
PRINT CHAR(13)+'--2.建立文件'
WHILE @i <= @PartNumber
BEGIN
    SET @PartNumberStr =  RIGHT('0' + CONVERT(NVARCHAR,@PartNumberBeginTemp),2)
    SET @sql = 'ALTER DATABASE ['+@DataBaseName +']
ADD FILE
(NAME = N''FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'_data'',FILENAME = N'''+@Location+'FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'_data.ndf'',SIZE = '+@Size+', FILEGROWTH = '+@FileGrowth+' )
TO FILEGROUP [FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'];'
    PRINT @sql + CHAR(13)
    SET @i=@i+1
    SET @PartNumberBeginTemp = @PartNumberBeginTemp+1
END


--3.建立分区函数
PRINT CHAR(13)+'--3.建立分区函数'
DECLARE @FunValueStr NVARCHAR(MAX)
DECLARE @PNB INT
SET @i = 1
SET @PNB = 1
SET @FunValueStr = convert(NVARCHAR(50),@FunValueBegin) + ','
WHILE @i < @PartNumber-1
BEGIN
    SET @FunValueStr = @FunValueStr + convert(NVARCHAR(50),(@FunValueBegin+@PNB*@FunValue)) + ','
    SET @i=@i+1
    SET @PNB=@PNB+1
END
SET @FunValueStr = substring(@FunValueStr,1,len(@FunValueStr)-1)
SET @sql = 'CREATE PARTITION FUNCTION
[Fun_'+@TableName+'_'+@ColumnName+'](INT) AS
RANGE RIGHT
FOR VALUES('+@FunValueStr+')'
PRINT @sql + CHAR(13)


--4.建立分区方案
PRINT CHAR(13)+'--4.建立分区方案'
DECLARE @FileGroupStr NVARCHAR(MAX) 
SET @i = 1
SET @PartNumberBeginTemp = @PartNumberBegin
SET @FileGroupStr = ''
WHILE @i <= @PartNumber
BEGIN
    SET @PartNumberStr =  RIGHT('0' + CONVERT(NVARCHAR,@PartNumberBeginTemp),2)
    SET @FileGroupStr = @FileGroupStr + '[FG_'+@TableName+'_'+@ColumnName+'_'+@PartNumberStr+'],'
    SET @i=@i+1
    SET @PartNumberBeginTemp = @PartNumberBeginTemp+1
END
SET @FileGroupStr = substring(@FileGroupStr,1,len(@FileGroupStr)-1)
SET @sql = 'CREATE PARTITION SCHEME
[Sch_'+@TableName+'_'+@ColumnName+'] AS
PARTITION [Fun_'+@TableName+'_'+@ColumnName+']
TO('+@FileGroupStr+')'
PRINT @sql + CHAR(13)


--5.分区函数的记录数
PRINT CHAR(13)+'--5.分区函数的记录数'
SET @sql = 'SELECT $PARTITION.[Fun_'+@TableName+'_'+@ColumnName+']('+@ColumnName+') AS Partition_num,
  MIN('+@ColumnName+') AS Min_value,MAX('+@ColumnName+') AS Max_value,COUNT(1) AS Record_num
FROM dbo.['+@TableName+']
GROUP BY $PARTITION.[Fun_'+@TableName+'_'+@ColumnName+']('+@ColumnName+')
ORDER BY $PARTITION.[Fun_'+@TableName+'_'+@ColumnName+']('+@ColumnName+');'
PRINT @sql + CHAR(13)

 

7.下面从新对QunList表进行设计,涉及的内容以下:

1) 在QunInfo数据库中建立分区表QunList,这里已经把原表的ID字段去掉了,这个字段并无太大的意义;

2) 以[QunNum]做为汇集索引,并且是惟一的,这个须要开启IGNORE_DUP_KEY = ON选项,这样才能够在批量插入的时候忽略重复值;

3) 对原表的[MastQQ]字段从int类型变成smallint ,[CreateDate]字段从varchar(10)类型变为date,数据类型修改是为了减小表占用的空间,

4) 使用刚刚建立好的分区方案,以后建立的索引进行索引对齐;

5) 对表使用行压缩,减小数据库占用空间;

6) 对表进行页压缩会更节省空间?

--建立优化后的QunList表
CREATE TABLE [dbo].[QunList](
    [QunNum] [int] NOT NULL,
    [MastQQ] [smallint] NULL,
    [CreateDate] [date] NULL,
    [Title] [varchar](22) NULL,
    [Class] [varchar](38) NULL,
    [QunText] [varchar](80) NULL,
 CONSTRAINT [PK_QunList2] PRIMARY KEY CLUSTERED 
(
    [QunNum] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, DATA_COMPRESSION = ROW) ON [Sch_QunList_QunNum]([QunNum])
) ON [Sch_QunList_QunNum]([QunNum])
GO

wps1D7B.tmp

(Figure1:GroupData原表结构)

wps1D8C.tmp

(Figure2:GroupData新表结构)

8.把11个数据库都合并到新建立的QunInfo的QunList表中;

--合并数据
DECLARE @tablename sysname
DECLARE @dbname sysname
DECLARE @sql NVARCHAR(max)

--游标
DECLARE @itemCur CURSOR
SET @itemCur = CURSOR FOR 
    SELECT db_name,table_name from [QunInfo].[dbo].[tables]

OPEN @itemCur
FETCH NEXT FROM @itemCur INTO @dbname,@tablename
WHILE @@FETCH_STATUS=0

BEGIN
    
    SET @sql = '
    INSERT INTO [QunInfo].[dbo].[QunList]
           ([QunNum]
           ,[MastQQ]
           ,[CreateDate]
           ,[Title]
           ,[Class]
           ,[QunText])
    SELECT [QunNum]
      ,[MastQQ]
      ,[CreateDate]
      ,[Title]
      ,[Class]
      ,[QunText]
    FROM ['+@dbname+'].[dbo].['+@tablename+']'
  
    EXEC(@sql)
    
    UPDATE [QunInfo].[dbo].[tables] SET status = 1 WHERE db_name = @dbname AND table_name = @tablename
    
    --返回SQL
    PRINT(@sql)PRINT('GO')+CHAR(13)

    FETCH NEXT FROM @itemCur INTO @dbname,@tablename
END 

CLOSE @itemCur
DEALLOCATE @itemCur

wps1D8D.tmp

(Figure3:QunList表分区记录数)

wps1D8E.tmp

(Figure4:QunList数据行压缩前)

wps1D8F.tmp

(Figure5:QunList数据行压缩后)

咱们使用页压缩修改表QunList,看看数据占用大小的状况:

--页压缩
ALTER TABLE [QunList]  
REBUILD WITH (DATA_COMPRESSION = PAGE );

wps1D9F.tmp

(Figure6:QunList数据页压缩后)

相关文章
相关标签/搜索