优化器存在着局限,无论RBO还是CBO;CBO在于不能根据不完善的统计数据得出更实际的执行策略,所以还是需要专业人员根据实际来调整sql
优化器的最优步骤,包括查询转换器、成本估算器、执行计划生成器
成本估算器,涉及3方面内容:
1、选择度-指满足条件的行在查询的结果集中所占比率
2、基数
3、成本
针对选择度做一个实践:
分别以3种Index来观察成本问题
表结构Sql
/*
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[emp]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[emp]
GO
CREATE TABLE [dbo].[emp] (
[eid] [int] NULL ,
[deptno] [int] NULL ,
[ename] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[job] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
SET NOCOUNT OFF
Create Unique Clustered Index CIndex
ON Emp (EID)
GO
--以下根据测试来生成其中一个
CREATE INDEX IDX_Dep_En
ON Emp (deptno, ename)
Go
Create Index IDX_Job_Dep
On Emp (Job ,deptno)
Go
Create Index IDX_Ename
On Emp (ename)
Go
*/
/*
随机生成100条数据,其中deptno=20有10条,like ’jone%'有5条,job='Seller'有40条
*/
/*
Declare @L_EID int;
Set @L_EID = 1;
While (@L_EID <= 100)
Begin
Insert Into Emp(eid ,deptno ,ename ,job) values (@L_EID ,@L_EID % 20 + 1 ,'Smith' ,'Clark');
Set @L_EID = @L_EID + 1;
End
Set @L_EID = (Cast((Rand(@L_EID) * 31415926) As int) + DATEPART(millisecond , getdate())) % 100 + 1;
Declare @L_I int;
Set @L_I = 0;
While(@L_I < 5)
Begin
Print @L_EID;
If Not Exists(Select 0 From Emp with(nolock) Where EID = @L_EID And ename = 'Jone')
Update Emp Set ename = 'Jone' where eid = @L_EID;
Select @L_I = Count(0) From Emp with(nolock) Where ename = 'Jone';
Set @L_EID = (Cast((Rand(@L_EID) * 31415926) As int) + DATEPART(millisecond , getdate())) % 100 + 1;
End
Set @L_I = 0;
While (@L_I < 20)
Begin
Print @L_EID;
If Not Exists(Select 0 From Emp with(nolock) Where EID = @L_EID And job = 'Seller')
Update Emp Set job = 'Seller' where eid = @L_EID;
Select @L_I = Count(0) From Emp with(nolock) Where job = 'Seller';
Set @L_EID = (Cast((Rand(@L_EID) * 31415926) As int) + DATEPART(millisecond , getdate())) % 100 + 1;
End
Set @L_I = 0;
While (@L_I < 10)
Begin
Print @L_EID;
If Not Exists(Select 0 From Emp with(nolock) Where EID = @L_EID And deptno = 20)
Update Emp Set deptno = 20 where eid = @L_EID;
Select @L_I = Count(0) From Emp with(nolock) Where deptno = 20;
Set @L_EID = (Cast((Rand(@L_EID) * 31415926) As int) + DATEPART(millisecond , getdate())) % 100 + 1;
End
*/
在查询分析器根据3次情况,均执行
Select * From emp Where deptno = 20 and ename like 'Jone%' And Job ='Seller'
执行计划如下:
Emp (deptno, ename)
Emp (Job ,deptno)
Emp (ename)
个人认为:Emp (deptno ,ename)索引最好