建立分区表,分区索引
数据模型
具体操作方法:
- 创建分区函数
首先要确定分区键,我们以条码号为临界点。
CREATE PARTITION FUNCTION ThreeIDCodeRangePFN(idcode)
AS
RANGE LEFT FOR VALUES (
'28052007', -- 28052007 条码段
'28052008', -- 28052008 条码段
'28052009', -- 28052009 条码段
.......
)
GO
在范围分区中,首先定义边界点:如果存在4个分区,则定义3个边界点值,并指定每个值是第一个分区的上边界 (LEFT)还是第二个分区的下边界 (RIGHT)。根据 LEFT 或 RIGHT指定,始终有一个空分区,因为该分区没有明确定义的边界点。
- 创建分区架构
- 创建分区函数(完成逻辑上的分区)后,必须将其与分区架构(物理上的分区)相关联,以便将分区定向至特定的文件组。
ALTER DATABASE Test ADD FILEGROUP [Teaching28052007]
ALTER DATABASE Test ADD FILEGROUP [Teaching28052008]
ALTER DATABASE Test ADD FILEGROUP [Teaching28052009]
- 创建物理文件,为了便于管理,我们把每个物理文件放到了一个单独的文件组里面,也可以选择多个
ALTER DATABASE Test
ADD FILE
(NAME = N' Teaching28052007' , FILENAME =N'D:MyDataMyLuTeaching28052007.ndf',SIZE =15MB,MAXSIZE = 150MB,FILEGROWTH = 15MB)
TO FILEGROUP [Teaching28052007]
ALTER DATABASE Test
ADD FILE
(NAME = N'Teaching28052008' , FILENAME =N'D:MyDataMyLuTeaching28052008.ndf',SIZE =15MB,MAXSIZE = 150MB,FILEGROWTH = 15MB)
TO FILEGROUP [Teaching28052008]
ALTER DATABASE Test
ADD FILE
(NAME = N'Teaching28052009' , FILENAME =N'D:MyDataMyLuTeaching28052009.ndf',SIZE =15MB,MAXSIZE = 150MB,FILEGROWTH = 15MB)
TO FILEGROUP [Teaching28052009]
- 做好以上准备工作之后,接下来就要建立分区架构,用来将逻辑上的分区(分区函数)和物理上的分区(文件组)关联起来
CREATE PARTITION SCHEME [ThreeIDCodeRangePScheme]
AS
PARTITION ThreeIDCodeRangePFN TO
( [Teaching28052007],[Teaching28052008],[ 28052009],
......
[PRIMARY] )
GO
- 创建分区表
定义分区函数(逻辑结构)和分区架构(物理结构)后,即可创建表来利用它们。表定义应使用的架构,而架构又定义函数。要将这三者结合起来,必须指定应该应用分区函数的列。
CREATE TABLE [dbo].[ObjIDCode](
[IDCode] [varchar] (32) NOT NULL,
[WarehouseID] [int] NULL,
[Batch] [varchar](32) COLLATE Chinese_PRC_CI_AS NULL,
......
) ON ThreeIDcodeRangePScheme(IDCode)
ALTER TABLE [ObjIDCode]
ADD CONSTRAINT [ObjIDCode_PK]
PRIMARY KEY CLUSTERED ([IDCode])
GO
- 最后就可以往分区表里面插入数据进行测试,SQL SERVER2005会根据之前定义好的分区函数按照分区键的不同将数据放到相应的分区,具体的可以通过下面的来查看数据存在那个分区中:
select $partition.ThreeIDCodeRangePFN(IDDode),IDCode,*
from objIDCode a
order by a.idcode asc
除了对表的数据集进行分区之外,还可以对索引进行分区。使用相同的函数对表及其索引进行分区通常可以优化性能。当索引和表按照相同的顺序使用相同的分区函数和列时,表和索引将对齐。如果在已经分区的表中建立索引,SQLServer 会自动将新索引与该表的分区架构对齐,除非该索引的分区明显不同。当表及其索引对齐后,SQL Server则可以更有效地将分区移入和移出分区表,因为所有相关的数据和索引都使用相同的算法进行划分。
如果定义表和索引时不仅使用了相同的分区函数,还使用了相同的分区架构,则这些表和索引将被认为是按存储位置对齐。按存储位置对齐的一个优点是,相同边界内的所有数据都位于相同的物理磁盘上。在这种情况下,可以单独在某个时间段内执行备份操作,还可以根据数据的变化在备份频率和备份类型方面改变您的策略。如果连接或收集了相同文件或文件组中的表和索引,则可以发现更多的好处。SQLServer 可以通过在多个分区中并行操作来获益。在按存储位置对齐和多 CPU的情况下,每个处理器都可以直接处理特定的文件或文件组,而不会与数据访问产生任何冲突,因为所有需要的数据都位于同一个磁盘上。这样,可以并行运行多个进程,而不会相互干扰。
- 创建索引,优化SQL语句。
A. 创建索引
影响到数据库性能的很大因素就是索引。我们重点讨论clustered索引(聚集索引)和nonclustered索引(非聚集索引)
当表格使用主关键字(primary keys),默认情况下SQLServer会自动对包含该关键字的column(s)建立一个独有的cluster索引。很显然,对这些column(s)建立独有索引意味着主关键字的唯一性。
当建立外关键字(foreignkey)关系时,如果你打算频繁使用它,那么在外关键字cloumn上建立nonclustered索引不失为一个好的方法。如果表格有clustered索引,那么它用一个链表来维护数据页之间的关系。相反,如果表格没有clustered索引,SQLServer将在一个堆栈中保存数据页。
何时使用聚集索引或非聚集索引
下面的表总结了何时使用聚集索引或非聚集索引(很重要)。
动作描述使用聚集索引使用非聚集索引
列经常被分组排序应应
返回某范围内的数据应不应
一个或极少不同值不应不应
小数目的不同值应不应
大数目的不同值不应应
频繁更新的列不应应
外键列应应
主键列应应
频繁修改索引列不应应
B. 优化SQL
很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQLSERVER误解。比如:
select * from table1 where name=''zhangsan'' and tID> 10000
和执行:
select * from table1 where tID > 10000 andname=''zhangsan''
一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那么后一句仅仅从表的10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name=''zhangsan''的,而后再根据限制条件条件tID>10000来提出查询结果。
事实上,这样的担心是不必要的。SQLSERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。
虽然查询优化器可以根据where子句自动的进行查询优化,但大家仍然有必要了解一下“查询优化器”的工作原理,如非这样,有时查询优化器就会不按照您的本意进行快速查询。
在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用索引快速获得所需数据。
SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的AND连接。形式如下:
列名 操作符 <常数 或 变量>
或
<常数 或 变量> 操作符列名
列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如:
Name=’张三’
价格>5000
5000<价格
Name=’张三’ and 价格>5000
如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQLSERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。
介绍完SARG后,我们来总结一下使用SARG以及在实践中遇到的和某些资料上结论不同的经验:
1、Like语句是否属于SARG取决于所使用的通配符的类型
如:name like ‘张%’ ,这就属于SARG
而:name like ‘%张’ ,就不属于SARG。
原因是通配符%在字符串的开通使得索引无法使用。
2、or 会引起全表扫描
Name=’张三’ and 价格>5000 符号SARG,而:Name=’张三’ or价格>5000 则不符合SARG。使用or会引起全表扫描。
3、非操作符、函数引起的不满足SARG形式的语句
不满足SARG形式的语句最典型的情况就是包括非操作符的语句,如:NOT、!=、<>、!<、!>、NOTEXISTS、NOT IN、NOT LIKE等,另外还有函数。下面就是几个不满足SARG形式的例子:
ABS(价格)<5000
Name like ‘%三’
有些表达式,如:
WHERE 价格*2>5000
SQL SERVER也会认为是SARG,SQL SERVER会将此式转化为:
WHERE 价格>2500/2
但我们不推荐这样使用,因为有时SQL SERVER不能保证这种转化与原始表达式是完全等价的。
4、IN 的作用相当于OR
语句:
Select * from table1 where tid in (2,3)
和
Select * from table1 where tid=2 or tid=3
是一样的,都会引起全表扫描,如果tid上有索引,其索引也会失效。
5、尽量少用NOT
6、exists 和 in 的执行效率是一样的
7、用函数charindex()和前面加通配符%的LIKE执行效率一样
8、union并不绝对比or的执行效率高
9、字段提取要按照“需多少、提多少”的原则,避免“select *”
10、order by按聚集索引列排序效率最高
11、高效的TOP
事实上,在查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0操作。
- 数据迁移
在指定的时间段内将旧数据迁移到另外的数据库。以提高当前数据库的查询速度。定期使用数据库管理工具对一定时间段内的数据进行拷贝迁移,并删除当前库中已经迁移的数据记录。
- 升级硬件
在海量数据,如 每年以 上亿的速度增长时,对硬件建议使用 8G以上的内存,采用双CPU或4CPU进行处理。
- 提高网速