统计信息对于sybase优化器创建一个好的计划非常重要。有时你会更新统计数据,但你仍然可以看到计划是坏的。这并不意味着优化器做出了错误的选择。这个选择是基于提供给它的信息。有时所提供的信息是不够的,或者某一列的统计数字不能正确地反映正在发生的事情。因此优化器可能会制定错误的计划。
其中一种情况是列数据有偏差,我们使用了默认值或更少的步数。
让我们在这里构建我需要的表。
设置
无计数
开启
删除表
删除表
mytab
创建表
rnumtab(rnum int identity not)null主键,col1 varchar(1)null)
insert into
rnumtab(col1)select top 5000'1'from syscolumns
create table
mytab(col1 int identity not null primary key,col2 int not null,col3 char(120)not null,col4 datetime not null)
insert into
mytab(col2,col3,col4)
select
a.rnum,convert(varchar(120),newid(1)),dateadd(mi,-1*(b.rnum*rand()),getdate())
from
rnumtab a inner join rnumtab b
on
a.rnum>=b.rnum
insert into
mytab(col2,col3,col4)选择col2,col3,来自mytab的col4,其中col2介于4990和5000之间
下降指数
mytab.idx\u 1
在mytab(col2)上创建索引
idx\u 1
删除索引
mytab.idx\u 2
在mytab(col4)上创建索引
idx_2
从mytab中选择计数
(*)
我查看了col2的optdiag输出,可以看到historgram中有5000个步骤,并且非常好,因为我的数据是倾斜的,更多的步骤意味着更好的统计数据。
我的服务器有直方图调整因子=20。
现在像其他人一样,我希望我的统计数据是最新的。因此,大数据指的是什么,我已经在索引上运行了updatestatistics。
update index statistics
mytab idx_1
现在检查optdiag输出,直方图只有31个步骤。这里发生了什么事?我想这是一个错误,因为除非明确指定,否则更新统计数据不应该减少直方图统计数据。
无论如何,我会和一些sybase的人讨论上面的问题。但这不是我讨论的重点。现在我有31个步骤,我的数据有很大的偏差。让我们运行一个示例查询。
设置showplan on
设置statistics io,time,plancost on
go
从mytab中选择
*,其中col2=10
这里是计划和统计。
========================Lava操作符树===============
Emit(VA=1)r:10 er:3380 cpu:0
/IndexScanidx\u 1(VA)=0)r:10 er:3380l:5 el:263p:0 ep:263
=======================================================表:mytab扫描计数1,逻辑读取:(常规=5 apf=0总计=5),有什么免费的云服务器,物理读取:(常规=0 apf=0总计=0),apf IOs used=0此命令的总写入数:0
执行时间0。自适应服务器cpu时间:0毫秒。自适应服务器运行时间:0毫秒。
查看估计行(3380
)与实际行(10)。即使我们有最新的数据,这也不好。但对于给定的查询,它做得很好,因为它选择了正确的计划。如果此表开始与其他一些表连接,并且估计的行可能会导致与其他表的合并/哈希连接,而不是嵌套循环连接(如对10行所做的那样),则情况可能会变糟。由于这个错误的估计,可能还有其他问题。今天,我将展示这样一个例子。
设置showplan on
设置statistics io,time,plancost on
go
从mytab中选择top 1
*,其中col2=10
order by col4 desc
让我们想想优化器应该为这个查询选择什么样的计划。我们在col2(idx_1)和col4(idx_2)上都有索引。但是,col2是我们的SARG,我们有col4的订单。
我们确信它应该选择col2的索引。这里所做的工作将是使用col2上的索引来获取所有行。然后根据col4对结果集排序并返回最顶层的行。这正是我和我们大多数人所期望的。现在让我们看看计划。
=====================熔岩操作符树=================
发射(VA=2)r:1 er:3380 cpu:100
/顶(VA=1)r:1er:3380 l:0 el:297 p:0 ep:297
/IndexScanidxè2(VA=0)r:1 er:3380l:29210 el:297p:0 ep:297
=======================================================表:mytab扫描计数1,逻辑读取:(常规=29210 apf=0总计=29210),物理读取:(常规=0 apf=0总计=0),apf IOs使用=0总计写入此命令:0
执行时间1.自适应服务器cpu时间:100毫秒。自适应服务器运行时间:113毫秒。
这里发生了什么?优化器选择col4上的索引而不是col2上的索引。这很奇怪,我团队中的每个人都认为这是一个Sybase bug。然而,我认为sybase optimizer选择col4上的索引是一种美。
我将解释它为什么选择col4上的索引。因为它选择col2上的索引。然后它必须将3380行(估计行)放入一个wroktable,然后在col4上排序并返回最上面的行。