调优过程

Posted 大叔聚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调优过程相关的知识,希望对你有一定的参考价值。

性能调优
1    百胜表规范 
USE ERP_DW
GO

/*
    功能说明: 创建【区域】维度表
    修改说明:    Create by LY on 2011-09-07
*/
IF EXISTS (SELECT 1
           FROM  SYSOBJECTS
           WHERE  id = OBJECT_ID(\'Dim_Area\')
           AND   type = \'U\')
BEGIN
    DROP TABLE Dim_Area
END
GO
CREATE TABLE [dbo].[Dim_Area] 
(
   AreaCode             VARCHAR(20)          NOT NULL,
   AreaName             VARCHAR(50)          NULL,
   CONSTRAINT PK_DIM_AREA PRIMARY key (AreaCode)
);
GO

/*
    功能说明: 获取区域表有效的信息
    修改说明:    Create by LY on 2011-09-07
*/
IF EXISTS (SELECT 1
           FROM SYSOBJECTS
           WHERE id = OBJECT_ID(\'VW_Dim_Area\')
           AND type = \'V\')
BEGIN
    DROP VIEW VW_Dim_Area
END
GO
CREATE VIEW VW_Dim_Area
AS
    SELECT AreaCode
    FROM Dim_Area LEFT JOIN SYSOBJECTS ON 1=1
                  LEFT JOIN SYSCOLUMNS ON 1=1
    WHERE 1=1
    GROUP BY AreaCode
GO

/*
    功能说明:抽取业务库的数据到数据仓库
    修改说明:    Create by LY on 2011-09-07
                Modify by LY on 2011-09-07   增加变量的注释
*/
IF EXISTS (SELECT 1
           FROM SYSOBJECTS
           WHERE id = OBJECT_ID(\'P_GetData_Load_Dim_Area\')
           AND OBJECTPROPERTY(ID, N\'IsProcedure\') = 1)
BEGIN
     DROP PROCEDURE  [dbo].[P_GetData_Load_Dim_Area]
END
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[P_GetData_Load_Dim_Area] 
    @P_sourceDB_name NVARCHAR(50)    ----源数据库名称,数据从哪抽取
AS
BEGIN
BEGIN TRAN   ---开始事务
    DECLARE @TrunSql VARCHAR(50);       ----清空数据,不记录日志
    DECLARE @InsertSql VARCHAR(MAX);    ----插入数据
    SET @TrunSql=\' TRUNCATE  Table Dim_Area \';
    EXEC (@TrunSql)
    IF @@error<>0    
    BEGIN 
         ROLLBACK TRAN     
         RETURN -1 
    END
    SET @InsertSql=\' INSERT INTO Dim_Area 
                     SELECT
                           QUYU.QYDM as AreaCode,
                           QUYU.QYMC as AreaName
                     FROM
                           ERP_Business..QUYU \';
                      
     EXEC(@InsertSql)
     IF @@ERROR<>0
     BEGIN
          ROLLBACK TRAN
          RETURN -1
     END
COMMIT TRAN
END;

GO


/*
    功能说明:抽取业务库的数据到数据仓库
    修改说明:    Create by LY on 2011-09-07
                Modify by LY on 2011-09-07   增加变量的注释
*/
IF OBJECT_ID(\'[dbo].[P_GetData_Load_Dim_Area]\',\'P\') IS NOT NULL 
    DROP PROC [dbo].[P_GetData_Load_Dim_Area]
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[P_GetData_Load_Dim_Area] 
    @P_sourceDB_name NVARCHAR(50)    ----源数据库名称,数据从哪抽取
AS
BEGIN
BEGIN TRAN   ---开始事务
    DECLARE @TrunSql VARCHAR(50);           ----清空数据,不记录日志
    DECLARE @InsertSql VARCHAR(MAX);        ----插入数据
    SET @TrunSql=\' TRUNCATE  Table Dim_Area \';
    EXEC (@TrunSql)
    IF @@error<>0   
    BEGIN 
         ROLLBACK TRAN     
         RETURN -1 
     END
    SET @InsertSql=\' INSERT INTO Dim_Area
                     SELECT
                           QUYU.QYDM as AreaCode,
                           QUYU.QYMC as AreaName
                     FROM
                           ERP_Business..QUYU \';
                      
     EXEC(@InsertSql)
     IF @@ERROR<>0
     BEGIN
          ROLLBACK TRAN
          RETURN -1
     END
COMMIT TRAN
END;
2    表分区
SQL Server引入的表分区技术,让用户能够把数据分散存放到不同的物理磁盘中,提高这些磁盘的并行处理性能以优化查询性能
2.1    表分区的介绍
    表分区的作用,优点,步骤
(1)分区表的作用:
在大量业务数据处理的项目中,可以考虑使用分区表来提高应用系统的性能并方便数据管理,本文详细介绍了分区表的使   用。在大型的企业应用或企业级的数据库应用中,要处理的数据量通常可以达到几十到几百GB,有的甚至可以到TB级。虽然存储介质和数据处理技术的发展也很快,但是仍然不能满足用户的需求,为了使用户的大量的数据在读写操作和查询中速度更快,Oracle提供了对表和索引进行分区的技术,以改善大型应用系统的性能。
(2)使用分区的优点:
增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;
改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
(3).分区表的步骤:
1.创建分区函数
2.创建映射到分区函数的分区方案
3.创建使用该分区方案的分区表
2.2    表分区的SQL步骤
    创建数据库的时候就创建分区的方案:
use Master
go

/*
    功能说明: 关闭数据库连接
    修改说明:    Create by LY on 2011-09-09
*/
if object_id(\'Proc_KillDataBase\',\'P\') is not null drop proc Proc_KillDataBase
go
create proc Proc_KillDataBase
@DataBaseName nvarchar(100)
as
begin
  DECLARE   @i   INT 
    SELECT   @i=1 
  DECLARE   @sSPID   VARCHAR(100) 

    DECLARE   KILL_CUR   SCROLL   CURSOR 
        FOR   
        SELECT   SPID   
        FROM   sysprocesses   
        WHERE   DBID=DB_ID(@DataBaseName)                 
        
    OPEN   KILL_CUR                 
    IF   @@CURSOR_ROWS   =   0   GOTO   END_KILL_CUR 
    FETCH   FIRST   FROM   KILL_CUR   INTO   @sSPID             
    EXEC( \'KILL   \'+@sSPID)               
    WHILE   @i <   @@CURSOR_ROWS 
    BEGIN     
        FETCH   NEXT   FROM   KILL_CUR   INTO   @sSPID             
        EXEC( \'KILL   \'+@sSPID) 
        SELECT   @i=@i+1 
    END 
END_KILL_CUR: 
    CLOSE   KILL_CUR 
    DEALLOCATE   KILL_CUR
end
go

EXEC Proc_KillDataBase \'PT_Sales\'
GO

/*
步骤一:
    功能说明: 创建Sales数据库,创建多个文件组,用于数据分区
    修改说明:    Create by LY on 2011-09-09
*/
IF EXISTS (SELECT 1
           FROM  sys.databases 
           WHERE  name = \'PT_Sales\')
BEGIN
    DROP DATABASE PT_Sales
END
GO
CREATE DATABASE PT_Sales ON PRIMARY     -----------一个主文件,三个文件组,一个日志文件
(    
  NAME = N\'Sales\',    
  FILENAME = N\'D:\\DB\\Sales.mdf\',    
  SIZE = 3MB, 
  MAXSIZE = 100MB,    
  FILEGROWTH = 10%    
),    
FILEGROUP FG1     
(    
  NAME = N\'File1\',    
  FILENAME = N\'D:\\DB\\PT\\File1.ndf\',    
  SIZE = 1MB,    
  MAXSIZE = 100MB,    
  FILEGROWTH = 10%    
),    
FILEGROUP FG2    
(    
  NAME = N\'File2\',    
  FILENAME = N\'D:\\DB\\PT\\File2.ndf\',    
  SIZE = 1MB,    
  MAXSIZE = 100MB, 
  FILEGROWTH = 10%    
), 
FILEGROUP FG3    
(    
  NAME = N\'File3\',    
  FILENAME = N\'D:\\DB\\PT\\File3.ndf\',    
  SIZE = 1MB,    
  MAXSIZE = 100MB,    
  FILEGROWTH = 10%    
)    
LOG ON    
(    
  NAME = N\'Sales_Log\',    
  FILENAME = N\'D:\\DB\\Sales_Log.ldf\',    
  SIZE = 1MB,    
  MAXSIZE = 100MB,    
  FILEGROWTH = 10% 
) 
GO


/*
步骤二:
    功能说明: 建立分区函数,这里我们建立三个分区。how(如何对数据进行分区)
    修改说明:    Create by LY on 2011-09-09
*/
USE PT_Sales
GO
CREATE PARTITION FUNCTION PT_OrderDate (datetime)
AS RANGE RIGHT    
FOR VALUES (\'2003/01/01\', \'2004/01/01\') --n不能超过999,创建的分区数等于n + 1 
GO

/*
步骤三:
    功能说明:   创建分区方案,关联到分区函数。where(在哪里对数据进行分区)
    修改说明:    Create by LY on 2011-09-09

*/
USE PT_Sales    
GO    
CREATE PARTITION SCHEME PS_OrderDate    
AS PARTITION PT_OrderDate    
TO (FG1, FG2, FG3)    
GO

/*
步骤四:
    功能说明:  创建分区表。创建表并将其绑定到分区方案。这里我们建立个表,表的结构一样。
               其中OrdersHistory表用于保存归档数据。


*/
USE PT_Sales    
GO    

IF EXISTS (SELECT 1
           FROM  SYSOBJECTS
           WHERE  id = OBJECT_ID(\'Orders\')
           AND   type = \'U\')
BEGIN
    DROP TABLE Orders
END
GO
/*订单分区表*/
CREATE TABLE dbo.Orders    
(    
  OrderID int identity(10000,1),    
  OrderDate datetime NOT NULL,    
  CustomerID int NOT NULL,    
  CONSTRAINT PK_Orders PRIMARY KEY (OrderID, OrderDate)    
)    
ON PS_OrderDate (OrderDate)    
GO   

/*归档表【历史表】*/
IF EXISTS (SELECT 1
           FROM  SYSOBJECTS
           WHERE  id = OBJECT_ID(\'OrdersHistory\')
           AND   type = \'U\')
BEGIN
    DROP TABLE OrdersHistory
END
GO
CREATE TABLE dbo.OrdersHistory    
(    
  OrderID int identity(10000,1),    
  OrderDate datetime NOT NULL,    
  CustomerID int NOT NULL,    
  CONSTRAINT PK_OrdersHistory PRIMARY KEY (OrderID, OrderDate)    
)    
ON PS_OrderDate (OrderDate)    
GO


USE PT_Sales    
GO    
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2002/6/25\', 1000)    
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2002/8/13\', 1000)    
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2002/8/25\', 1000)    
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2002/9/23\', 1000) 
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2003/6/25\', 1000) 
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2003/8/13\', 1000) 
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2003/8/25\', 1000) 
INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES (\'2003/9/23\', 1000)    
GO


SELECT * FROM dbo.Orders    
SELECT * FROM dbo.OrdersHistory

/* 查看某一个分区
   这里我们要用到$PARTITION 函数,这个函数可以帮助我们查询某个分区的数据,
   还可以检索某个值所隶属的分区号。$PARTITION 函数的进一步细节可以查看MSDN

   查询已分区表Order的第一个分区,代码如下:
*/
SELECT * 
FROM dbo.Orders 
WHERE $PARTITION.PT_OrderDate(OrderDate) = 2


/*
   我们还可以查询某个分区有多少行数据,代码如下:
*/
SELECT $PARTITION.PT_OrderDate(OrderDate) AS Partition, 
COUNT(*) AS [COUNT]    
FROM dbo.Orders    
GROUP BY $PARTITION.PT_OrderDate(OrderDate)    
ORDER BY Partition ; 


/*
 我们还可以通过$PARTITION 函数获得一组分区标示列值的分区号,
 例如获得属于哪个分区,代码如下:
 
 很明显,年隶属于第个分区,因为我们建立分区函数时用了RANGE RIGHT,所以返回。
 你也可以把年换成,,,等等测试。你会发现,年属于第个分区,
 2004年以后的都属于第个分区。

*/
SELECT PT_Sales.$PARTITION.PT_OrderDate(\'2003\')

/*
归档数据
     假如现在是年年初,那么我们就可以把年所有的交易记录
     归档到历史订单表HistoryOrder中。代码如下:

*/
USE PT_Sales    
GO    
ALTER TABLE dbo.Orders SWITCH PARTITION 1 TO dbo.OrdersHistory PARTITION 1 
GO

SELECT * FROM dbo.Orders         
SELECT * FROM dbo.OrdersHistory

/*
便会发现,Orders 表只剩年的数据,而OrdersHistory表中包含了年的数据。
当然如果到了年年初,我们也可以归档年的所有交易数据。代码如下:
*/

USE PT_Sales    
GO    
ALTER TABLE dbo.Orders SWITCH PARTITION 2 TO dbo.OrdersHistory PARTITION 2 
GO


/* 
  添加分区:
      ALTER PARTITION SCHEME ps_OrderDate NEXT USED FG2 用来指定新分区的数据存储在那个文件。这里NEXT USED FG2 代表我们将新分区的数据保存在FG2文件组中,当然我们也可以在原有数据库上新建一个文件组,把新分区的数据保存在新文件组当中,这里我们直接用FG2文件组。
      ALTER PARTITION FUNCTION pf_OrderDate() SPLIT RANGE (\'2005/01/01\') 代表我们创建一个新分区,而这里SPLIT RANGE (\'2005/01/01\')正是创建新分区的关键语法。
      执行完上面的代码之后,我们就有了个分区,此时的区间如下: 
*/

USE PT_Sales    
GO    
ALTER PARTITION SCHEME PS_OrderDate NEXT USED FG2    
ALTER PARTITION FUNCTION PT_OrderDate() SPLIT RANGE (\'2005/01/01\') 
GO

/*
  删除分区:
  删除分区又称为合并分区,假如我们想合并年的分区和年的分区到一个分区,我们可以用如下的代码:

*/
USE PT_Sales    
GO    
ALTER PARTITION FUNCTION PT_OrderDate() MERGE RANGE (\'2003/01/01\') 
GO

/*
你会发现返回的结果是。而原来返回的是,原因是年以前数据所在的那个分区合并到了年这个分区中了。
假如此时我们执行如下代码:
*/

SELECT PT_Sales.$PARTITION.PT_OrderDate(\'2003\')

/*
结果一行数据都没返回,事实就这样,因为OrdersHistory 表中只存储了
2002和年的历史数据,在没有合并分区之前,执行上面的代码肯定会
查询出年的数据,但是合并了分区之后,上面代码实际查询的是第二个分区中年的数据。
*/
SELECT * 
FROM dbo.OrdersHistory    
WHERE $PARTITION.PT_OrderDate(OrderDate) = 2
/*
便会查询出行数据,包括年和年的数据,因为合并分区
后年和年的数据都成了第个分区的数据了。

*/
SELECT * 
FROM dbo.OrdersHistory    
WHERE $PARTITION.PT_OrderDate(OrderDate) = 1


/*
查看源数据
*/
select * from sys.partition_functions    
select * from sys.partition_range_values 
select * from sys.partition_schemes

2.3    将普通表转换成分区表
    将普通表转换为分区表的做法
/*
    功能说明:将普通表转换成分区表.

    介绍:    在以上代码中,我们可以看出,这个表拥有一般普通表的特性——有主键,同时这个主键还是聚集索引。
             前面说过,分区表是以某个字段为分区条件,所以,除了这个字段以外的其他字段,是不能创建聚集
             索引的。因此,要想将普通表转换成分区表,就必须要先删除聚集索引,然后再创建一个新的聚集索
             引,在该聚集索引中使用分区方案。

            可惜的是,在SQL Server中,如果一个字段既是主键又是聚集索引时,并不能仅仅删除聚集索引。因此,
            我们只能将整个主键删除,然后重新创建一个主键,只是在创建主键时,不将其设为聚集索引,如以下
            代码所示:

*/

/*
     功能说明:创建文件组
*/
USE ERP_DW
GO

ALTER DATABASE ERP_DW
ADD FILEGROUP [FG_ERP_DW_01]

ALTER DATABASE ERP_DW
ADD FILEGROUP [FG_ERP_DW_02]

ALTER DATABASE ERP_DW
ADD FILEGROUP [FG_ERP_DW_03]

GO


/*

*/


/*
      功能说明:创建文件
*/

ALTER DATABASE ERP_DW
ADD FILE
(
    NAME = N\'FG_ERP_DW_01_data\',
    FILENAME = N\'D:\\DB\\PT\\FG_ERP_DW_01_data.ndf\',
    SIZE = 30MB, 
    FILEGROWTH = 10% 
 )
TO FILEGROUP [FG_ERP_DW_01];

ALTER DATABASE ERP_DW
ADD FILE
(
    NAME=N\'FG_ERP_DW_02_date\',
    FILENAME=N\'D:\\DB\\PT\\FG_ERP_DW_02_data.ndf\',
    SIZE=30MB,
    FILEGROWTH=10%
)
TO FILEGROUP 以上是关于调优过程的主要内容,如果未能解决你的问题,请参考以下文章

记一次线上gc调优的过程

JVM 性能调优实战之:一次系统性能瓶颈的寻找过程

Sublime Text自定制代码片段(Code Snippets)

一个典型的测试压力机的性能调优过程

一次JVM GC引发的Spark调优大全(建议收藏)

当活动被破坏但我必须继续执行片段中的代码时该怎么办?