zoukankan      html  css  js  c++  java
  • SQL2005 表分区

    我用sqlserver2005的分区表功能,建了一个大数据量的分区表,
    过程如下:
    建文件组
    ALTER DATABASE [aqs2211] ADD FILEGROUP [fg2008]
    ALTER DATABASE [aqs2211] ADD FILEGROUP [fg2009]
    ALTER DATABASE [aqs2211] ADD FILEGROUP [fg2010]
    ALTER DATABASE [aqs2211] ADD FILEGROUP [fg2011]
    ALTER DATABASE [aqs2211] ADD FILEGROUP [fg2012]

    ALTER DATABASE [aqs2211] ADD FILE
    (NAME = N'aqs2211_Data2008',
    FILENAME = N'G:\xp\data\aqs2211_Data2008.ndf',
    SIZE = 2048KB , FILEGROWTH = 1024KB ) TO FILEGROUP [fg2008]

    ALTER DATABASE [aqs2211] ADD FILE
    (NAME = N'aqs2211_Data2009',
    FILENAME = N'G:\xp\data\aqs2211_Data2009.ndf',
    SIZE = 2048KB , FILEGROWTH = 1024KB ) TO FILEGROUP [fg2009]


    ALTER DATABASE [aqs2211] ADD FILE
    (NAME = N'aqs2211_Data2010',
    FILENAME = N'G:\xp\data\aqs2211_Data2010.ndf',
    SIZE = 2048KB , FILEGROWTH = 1024KB ) TO FILEGROUP [fg2010]


    ALTER DATABASE [aqs2211] ADD FILE
    (NAME = N'aqs2211_Data2011',
    FILENAME = N'G:\xp\data\aqs2211_Data2011.ndf',
    SIZE = 2048KB , FILEGROWTH = 1024KB ) TO FILEGROUP [fg2011]


    ALTER DATABASE [aqs2211] ADD FILE
    (NAME = N'aqs2211_Data2012',
    FILENAME = N'G:\xp\data\aqs2211_Data2012.ndf',
    SIZE = 2048KB , FILEGROWTH = 1024KB ) TO FILEGROUP [fg2012]

    建分区函数:
    CREATE PARTITION FUNCTION auditinfotb_pf ( datetime )
    AS RANGE right
    FOR VALUES ('2008-01-01','2009-01-01','2010-01-01','2011-01-01')

    建分区架构:
    CREATE PARTITION FUNCTION auditinfotb_pf ( datetime )
    AS RANGE right
    FOR VALUES ('2008-01-01','2009-01-01','2010-01-01','2011-01-01')

    建分区表
    CREATE TABLE auditinfotb (
    id char(20) NOT NULL ,
    localCode varchar(6) ,
    appCode char(5) NOT NULL ,
    userIP varchar(15) DEFAULT NULL ,
    userRoleCode varchar(80) DEFAULT NULL ,
    privilegeCode varchar(512) DEFAULT NULL ,
    succeed char(1) DEFAULT NULL ,
    errMsg varchar(256) DEFAULT NULL ,
    isLocalUser char(1) DEFAULT NULL ,
    accessTime datetime NOT NULL ,
    userName varchar(128) NOT NULL ,
    userIDN varchar(32) DEFAULT NULL ,
    orgCode char(12) DEFAULT NULL ,
    policeType char(2) DEFAULT NULL ,
    dutyLevel char(4) DEFAULT NULL ,
    station char(4) DEFAULT NULL ,
    charge char(4) DEFAULT NULL ,
    ministry char(3) DEFAULT NULL ,
    certRole char(6) DEFAULT NULL ,
    orgName varchar(256) DEFAULT NULL ,
    appName varchar(256) DEFAULT NULL ,
    appType char(4) DEFAULT NULL,
    provCode char(2) DEFAULT NULL ,
    cityCode char(2) DEFAULT NULL ,
    countyCode char(2) DEFAULT NULL ,
    unit1Code char(2) DEFAULT NULL ,
    unit2Code char(2) DEFAULT NULL,
    unit3Code char(2) DEFAULT NULL ,
    ) ON auditinfotbPS(accesstime)
    ;

    分区表建好后我用导入导出工具,把数据导入进来
    然后创建索引
    create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);

    索引建好后,我查询某日的记录的时候
    比如:
    select *from auditinfotb
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'
    就会全表扫描,
    而另一个时间段比如
    select *from auditinfotb
    where accesstime>'2009-09-06'
    and accesstime<'2009-09-07' 就会利用上索引,
    这是怎么回事呢?

    索引建好后,我查询某日的记录的时候
    比如:
    select *from auditinfotb
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'
    就会全表扫描,
    而另一个时间段比如
    select *from auditinfotb
    where accesstime>'2009-09-06'
    and accesstime<'2009-09-07' 就会利用上索引,

    要不要用索引会根据你的数据统计信息,

    假如你的表里面数据1000条,
    '2009-06-01'的数据才1条两条

    '2009-09-06'是表里面有几百条,

    第一个肯定会用索引查找,再有序局部扫描加书签
    第二个不在选择点上,则选择表扫描会更快,书签查找是比较耗费I/O的

    补充:
    比如
    select * from auditinfotb2
    where accesstime>'2009-05-01'
    and accesstime<'2009-05-02'
    能利用索引
    这部分数据是44051条
    而select * from auditinfotb2
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'
    就需要全部扫描,这部分数据是134716
    这些数据相对于整个分区表8千多万数据来说,某一天的还是很少的,没道理利用不上索引的,而且
    select count(*) from auditinfotb2
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'的话,也能利用上索引,这又是怎么回事呢?

    分区表建好后我用导入导出工具,把数据导入进来
    然后创建索引
    create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode)
    ON auditinfotbPS(accesstime)

    你的表没有聚集索引,应该

    create CLUSTERED index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode)
    ON auditinfotbPS(accesstime)

    而select * from auditinfotb2
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'
    就需要全部扫描,这部分数据是134716
    这些数据相对于整个分区表8千多万数据来说,某一天的还是很少的,没道理利用不上索引的,而且
    select count(*) from auditinfotb2
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'的话,也能利用上索引,这又是怎么回事呢?

    没道理利用不上索引???那你觉得为什么要用得上索引呢,??有时候是会估算失败,你可以尝试指定你的索引执行看一下效率.


    select count(*) from auditinfotb2
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'的话,也能利用上索引,这又是怎么回事呢?
    这是COUNT(*) 不是*,
    *号是所有数据,页COUNT(*)只是一个标量聚合,只取行数就行了,不用把数据给弄出来

    6/1=13471笔,如果使用索引seek,那么意味着至少有13471个随机IO(忽略索引层级不谈).

    通常随机IO的代价要远远高于顺序IO,因为数据分布的问题,随机IO需要移动更多次的磁臂才能读取到数据,而
    顺序IO可以使用预读等机制提供更快的读取速度。

    回到你的问题,在未分区前,8000W的数据做scan可代价要高于13471次随机IO,故会使用seek.

    但分区后,变成只需要扫描一个表分区即可,所以,优化器会更倾向于选择分区表扫描。

    再看你提的
    select top 20 * From auditinfotb
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'
    ------------耗时32秒
    select top 20 * From auditinfotb with (index=index_auditinfo_orgcode)
    where accesstime>'2009-06-01'
    and accesstime<'2009-06-02'
    ------------- 耗时0秒

    第2个查询耗时0秒的原因是,SQLSERVER只使用了20次索引查找,所以耗时很短。这样没有什么可比性。

    要了解优化器为什么没有采用索引查找,请打开IO/CPU读数,把TOP 20 去掉,然后再比较看看。

  • 相关阅读:
    单变量线性回归
    【记】国奖交流会
    转【研究生第一篇学术论文常犯问题总结】
    this.$confirm里面使用await异步调取接口数据
    margin和padding的值是百分比的时候是怎么计算的?
    原生js实现三级联动下拉框
    两个数组里面的对象元素根据相同的id合并到一个数组
    制作遮罩层的样式
    自定义表单验证方法的使用
    封装获取操作系统和浏览器类型的方法
  • 原文地址:https://www.cnblogs.com/zzxap/p/2175770.html
Copyright © 2011-2022 走看看