<海量数据库解决方案>2011031401

优化器存在着局限,无论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)索引最好

原文地址:https://www.cnblogs.com/GoGoagg/p/1983277.html