• 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 去掉,然后再比较看看。

  • 相关阅读:
    最近在学习vala,并打算用它写点东西, 先上个习作 -- popplersample
    GTK# 学习笔记
    monodevelop2.0在SmartQ5上成功运行
    c, cs, vala 性能简单测试
    在Q5上用vala写程序
    树结构型数据在基于关系型数据库的分布式应用的解决方案
    常用常忘的delegate,记一下。
    JSON
    HTML5脚本编程
    event事件对象
  • 原文地址:https://www.cnblogs.com/zzxap/p/2175770.html
Copyright © 2020-2023  润新知