补充:
比如
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'的话,也能利用上索引,这又是怎么回事呢?
?
Haiwer? 回复于:2010-07-13 11:27:42
分区表建好后我用导入导出工具,把数据导入进来
然后创建索引
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) ;
?
xpcc?? 回复于:2010-07-13 11:41:08
to Haiwer(海阔天空)?
一定要建聚集索引吗?非聚集索引不行吗?
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode)
ON auditinfotbPS(accesstime);
和
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);
应该是一样的吧?
?
?
SQL77?? 回复于:2010-07-14 09:10:17
而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(*)只是一个标量聚合,只取行数就行了,不用把数据给弄出来
?
?
xpcc? 回复于:2010-07-14 10:04:24
to SQL77:
我觉得'2009-06-01'的记录是134716,相对于所在分区的3千多万记录来说是很少的,
(几个分区的记录数如下:
3 34687516
1 14474092
4 7721438
2 25723830
)
在有索引的情况下是应该走索引的。我如果用with (index=...) 强制使用索引的话,就能利用上索引,返回结果就很快
?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秒
再看你提的
?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秒
to Garnett_KG:
select * From auditinfotb?
where accesstime>'2009-06-01'
and accesstime<'2009-06-02'
----1分51秒
select * From auditinfotb with (index=index_auditinfo_orgcode)
where accesstime>'2009-06-01'
and accesstime<'2009-06-02'
------22秒
另外:打开“IO/CPU读数”是什么意思,是studio里面“查询”菜单中的“包含实际的执行计划”么?
另外:程序中是翻页查询的,所以语句中是有top关键字的,怎样才能让查询优化器判断应该走索引呢?
?
?
Garnett_KG?? 回复于:2010-07-14 15:34:23
你可以打开profiler看看这两条语句的reads/cpu各是多少。
也可以打开以下开关,看执行的效率
set statistics io on
set statistics time on
?
?
xpcc?? 回复于:2010-07-14 15:38:02
补充:
select * From auditinfotb?
where accesstime>'2009-06-01 00:00:00.000'
and accesstime<'2009-06-01 23:06:43.000'
---13秒--133232行--能利用索引
select * From auditinfotb?
where accesstime>'2009-06-01 00:00:00.000'
and accesstime<'2009-06-01 23:06:44.000'
---1分53秒--133234行--全表扫描
优化器判断到了到达一定量就要走全表扫描?可是这133234条是临界点?
而
select * From auditinfotb?
where accesstime>'2009-06-02 00:00:00.000'
and accesstime<'2009-06-02 18:24:44.000'
--10秒--119654行--索引扫描
select * From auditinfotb?
where accesstime>'2009-06-02 00:00:00.000'
and accesstime<'2009-06-02 18:24:45.000'
--1分52秒--119656行--表扫描
临界点是变化的?
?
?
xpcc?? 回复于:2010-07-14 15:55:10
to Garnett_KG:
使用:
set statistics io on
set statistics time on
-----------1-----------
select * From auditinfotb?
where accesstime>'2009-06-01'
and accesstime<'2009-06-02'
1)再加上一个开关
set statistics profile on
set statistics io on
set statistics time on
把CPU的耗用也贴出来。
2) 执行 UPDATE STATISTICS auditinfotb WITH FULLSCAN
然后再比较一次。
xpcc?? 回复于:2010-07-14 16:33:09
to Garnett_KG:
set statistics profile on set statistics io on set statistics time on
-------1---------- select * From auditinfotb? where accesstime>'2009-06-01' and accesstime<'2009-06-02' ----结果--- SQL Server 分析和编译时间:? ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 执行时间: ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。 SQL Server 分析和编译时间:? ? CPU 时间 = 0 毫秒,占用时间 = 6 毫秒。 SQL Server 分析和编译时间:? ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 执行时间: ? CPU 时间 = 7906 毫秒,占用时间 = 112579 毫秒。 SQL Server 分析和编译时间:? ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 执行时间: ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
134716 1 SELECT * FROM [auditinfotb] WHERE [accesstime]>@1 AND [accesstime 134716 1 |--Parallelism(Gather Streams) 1 2 1 Parallelism Gather Streams 134716 4 |--Table Scan(OBJECT:([aqs2211].[dbo].[auditinfotb]),WHERE:(
-------------2------------- select * From auditinfotb with (index=index_auditinfo_orgcode) where accesstime>'2009-06-01' and accesstime<'2009-06-02' --结果----- SQL Server 分析和编译时间:? ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 执行时间: ? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。 SQL Server 分析和编译时间:? ? CPU 时间 = 0 毫秒,占用时间 = 222 毫秒。
to Garnett_KG:
不好意思,是我定楼的没写对,
我最开始是
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);
发现索引利用不好,又删了反复试了几次,
最近这次的索引是
create index INDEX_auditinfo_orgcode on auditinfotb (orgcode);
我记得这样在分区表上建索引是默认的对齐索引,sqlserver自动在索引列里加上分区字段accesstime,
我以为
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);
和
create index INDEX_auditinfo_orgcode on auditinfotb (orgcode);
效果是一样的,所以也在顶楼粘了最开始的语句。
而且我也建过下面这样的索引
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime);
效果一样。
不过,昨晚我又用
create CLUSTERED index INDEX_auditinfo_2_orgcode2 on auditinfotb (accesstime)
ON auditinfotbPS2(accesstime);
这个语句建了聚集索引,这次没蓝屏。
我这回再查就能会聚集索引扫描了。
看来这种在分区表中按范围过滤记录是必须建聚集索引才能利用索引了?
?
?
Garnett_KG?? 回复于:2010-07-15 09:42:05
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);
和
create index INDEX_auditinfo_orgcode on auditinfotb (orgcode);
的效果肯定不一样啦!!
注意键值的顺序问题,orgcode在前的话 where accesstime>@1 and accesstime<@2 是无法使用索引的。
难怪看你的执行计划中即使你强制使用index也是走的scan.
xpcc?? 回复于:2010-07-15 09:45:57
如果分区表必须建一个聚集索引的话,那我还有个疑问
我这个大表在分区前建的是如下几个索引:
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);
create index INDEX_auditinfo_username on auditinfotb (accesstime,username);
create index INDEX_auditinfo_useridn on auditinfotb (useridn,accesstime);
create index INDEX_auditinfo_userip on auditinfotb (userip,accesstime);
create index INDEX_auditinfo_appcode on auditinfotb (appcode,accesstime);
分别对应程序查询页面的5个条件,这样无论选什么条件都能保证利用上一个索引,能很快的进行分页查询
那么,现在我把表进行分区了,那必须建个聚集索引
create CLUSTERED index INDEX_auditinfo_time on auditinfotb (accesstime);
那我还有必要建上面那5个索引么?似乎在count(*)的时候,上面5个索引也能利用上,不过如果没有这
5个索引,只用这个聚集索引是否也慢不到哪去呢?
?
Garnett_KG?? 回复于:2010-07-15 09:51:14
你不要把分区表跟聚集索引搞混了。
这两个东西可以独立存在的,不是说你分区后就必须要建聚集索引。
你的最开始的问题在于分区后索引没有建正确(orgcode,accesstime),所以没有用上索引。 你后来在accesstime上建立聚集索引后,where acesstime>@1 and accesstime@<@2 自然就可以index seek
xpcc?? 回复于:2010-07-15 10:20:06
to Garnett_KG:
我最开始是create index INDEX_auditinfo_orgcode on auditinfotb (accesstime,orgcode);
后来也
create index INDEX_auditinfo_orgcode on auditinfotb (accesstime);
过,
效果都是有时能利用上索引,有时利用不上。
如果说现在索引顺序不对的话,那它在查找出的记录数少的使用应该也不走索引的呀,而现在的现象似乎是查出的结果集超过一定量就利用不上索引。
?
?
xpcc??? 回复于:2010-07-15 10:40:31
to Garnett_KG:
下面测试数据是我另一个环境上的,win7+sqlserver2008
------1----------------
select * From auditinfotb
where accessTime>'2009-06-01'
and accessTime<'2009-06-05'
查询结果返回:9分43秒 529809行
执行计划:
SELECT * FROM [auditinfotb] WHERE [accessTime]>@1 AND [accessTime]<@2
? |--Table Scan(OBJECT:([aqs2212].[dbo].[auditinfotb]),SEEK:([PtnId1001]=(3)),WHERE:([aqs2212].[dbo].[auditinfotb].[accessTime]>'2009-06-01 00:00:00.000' AND [aqs2212].[dbo].[auditinfotb].[accessTime]<'2009-06-05 00:00:00.000') ORDERED FORWARD)
io/cpu:
SQL Server 分析和编译时间:?
? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 分析和编译时间:?
? CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
?SQL Server 执行时间:
? CPU 时间 = 13073 毫秒,占用时间 = 575729 毫秒。 ?
---------------2-------------------
select * From auditinfotb with (index=index_auditinfo_orgcode)
where accessTime>'2009-06-01'
and accessTime<'2009-06-05'
返回结果:37秒 529809行
执行计划:
select * From auditinfotb with (index=index_auditinfo_orgcode) where accessTime>'2009-06-01' and accessTime<'2009-06-05'
? |--Nested Loops(Inner Join,OUTER REFERENCES:([Bmk1000],[PtnId1001],[Expr1006]) OPTIMIZED WITH UNORDERED PREFETCH)
? |--Compute Scalar(DEFINE:([Expr1005]=BmkToPage([Bmk1000])))
? | |--Index Seek(OBJECT:([aqs2212].[dbo].[auditinfotb].[INDEX_auditinfo_orgcode]),SEEK:([PtnId1001]=(3) AND [aqs2212].[dbo].[auditinfotb].[accessTime] > '2009-06-01 00:00:00.000' AND [aqs2212].[dbo].[auditinfotb].[accessTime] < '2009-06-05 00:00:00.000') ORDERED FORWARD)
? |--RID Lookup(OBJECT:([aqs2212].[dbo].[auditinfotb]),SEEK:([PtnId1001]=[PtnId1001] AND [Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD) ?
io、cpu:
SQL Server 分析和编译时间:?
? CPU 时间 = 0 毫秒,占用时间 = 984 毫秒。