索引生成器

索引生成器

------------------------------------------------------------------------------------------------------------------

-- Author : HappyFlyStone

-- Date   : 2009-09-09

-- Version: Microsoft SQL Server 2005 - 9.00.2047.00 (Intel X86)

--       Apr 14 2006 01:12:25

--       Copyright (c) 1988-2005 Microsoft Corporation

--       Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 2)

--  本文探讨根据SQL Server 2005动态管理对象生成相应查询索引

--  更多精彩在happyflystone -CSDN博客

--  转载请标明出处:http://blog.csdn.net/happyflystone

-----------------------------------------------------------------

本程序只是根据动态管理对内暂存的计划生成相应的索引,你可以根据实际情况决定是否使用它。下面是本人用实际例子所生成索引的前后比较情况:(请大家不要对用例数据及相应查询SQL深究,仅是为了配合生成的索引做比较)

/*

没有任何索引的情况:

'tb'。扫描计数1,逻辑读取40 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

'ta'。扫描计数1,逻辑读取82 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

*/

 

/*

智能生成索引后的情况:

'tb'。扫描计数1,逻辑读取6 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

'ta'。扫描计数1,逻辑读取3 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

*/

--首先生成测试表

create table ta(id int,tb_id char(1),[name] varchar(60),price numeric(12,2))

create table tb(id char(1),typename varchar(20),ifuse char(1))

go

--生成测试数据

set nocount on

declare @i int

set @i = 0

while @i <10000

begin

    insert ta select @i,left(newid(),1),newid(),ascII(left(newid(),1))*ascII(right(newid(),1))

    set @i = @I +1

end

go

insert tb

select distinct tb_id,'test'+tb_id ,1

from ta

go 1000

--删除所有索引,这个过程大家可以访问我的blog

exec sp_dropallindex 'ta'

exec sp_dropallindex 'tb'

--无索引下执行此查询

set statistics io on

go

select a.id ,[typename],price

from ta a

join tb b  on a.tb_id =a.tb_id

where a.id = 1033 and b.id ='8' and price > 2500

set statistics io off

set nocount off

go

/*

'tb'。扫描计数1,逻辑读取40 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

'ta'。扫描计数1,逻辑读取82 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

*/

--智能索引后,参数1代表生成索引计划并执行,你可以用非1的字符,过程仅生成索引文本不执行,此过程请见附录

exec sp_autoIdx '1'

go

set statistics io on

go

select a.id ,[typename],price

from ta a

join tb b  on a.tb_id =a.tb_id

where a.id = 1033 and b.id ='8' and price > 2500

set statistics io off

set nocount off

 

/*

'tb'。扫描计数1,逻辑读取6 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

'ta'。扫描计数1,逻辑读取3 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

 

(1 行受影响)

*/

 

--删除测试用例

drop proc sp_autoIdx

drop table ta,tb

 

附录:

/*

exec sp_autoIdx ‘1’

or

exec sp_autoIdx ‘0’

@ifexec决定是否直接exec(@sqlon)在当前数据库生成索引。

转载请标明出处:http://blog.csdn.net/happyflystone

*/

CREATE PROC sp_autoIdx

@ifexec CHAR(1)

AS

BEGIN

 

    DECLARE @TB NVARCHAR(40)

    DECLARE @SQLON VARCHAR(200),@SQLINCLUDE VARCHAR(200)

    DECLARE CUR CURSOR FOR

        SELECT distinct STATEMENT

       FROM SYS.DM_DB_MISSING_INDEX_DETAILS AS MID

       CROSS APPLY SYS.DM_DB_MISSING_INDEX_COLUMNS (MID.INDEX_HANDLE)

       INNER JOIN SYS.DM_DB_MISSING_INDEX_GROUPS AS MIG ON MIG.INDEX_HANDLE = MID.INDEX_HANDLE

       ORDER BY STATEMENT asc

    OPEN CUR

    FETCH CUR INTO @TB

    WHILE(@@FETCH_STATUS = 0)

    BEGIN

       PRINT '--'+@TB+':'

       SET @SQLON = 'CREATE INDEX IDX_'+upper(PARSENAME (@tb,1))+'_'+replace(CAST(NEWID() AS VARCHAR(60)),'-','_')+' ON '+ @TB+'('

       SET @SQLINCLUDE=' INCLDE('

       ;WITH T

       AS

        (SELECT mig.*, statement AS table_name,

        column_id, column_name, column_usage,

       rowid = row_number() over(partition by index_group_handle ,statement order by index_group_handle,case column_usage when 'EQUALITY' THEN 1 WHEN 'INEQUALITY' THEN 2 ELSE 3 END),

        levelid = rank()over(partition by index_group_handle ,statement order by index_group_handle)

       FROM sys.dm_db_missing_index_details AS mid

       CROSS APPLY sys.dm_db_missing_index_columns (mid.index_handle)

       INNER JOIN sys.dm_db_missing_index_groups AS mig ON mig.index_handle = mid.index_handle)

        SELECT @SQLON= @SQLON+ CASE WHEN COLUMN_USAGE IN( 'EQUALITY' , 'INEQUALITY') THEN COLUMN_NAME+',' ELSE '' END ,

        @SQLINCLUDE= @SQLINCLUDE+ CASE WHEN COLUMN_USAGE ='INCLUDE' THEN COLUMN_NAME+',' ELSE '' END

       FROM T

       WHERE TABLE_NAME = @TB AND LEVELID = 1

       IF RIGHT(@SQLON,1)='('

           PRINT '根据动态管理对象无法智能生成索引计划'

       ELSE

       BEGIN

           SET @SQLON=LEFT(@SQLON,LEN(@SQLON)-1)+')'

           IF RIGHT(@SQLINCLUDE,1)='('

               PRINT @SQLON

               IF @IFEXEC = '1'

                   EXEC(@SQLON)

           ELSE

           BEGIN

               SET @SQLINCLUDE= LEFT(@SQLINCLUDE,LEN(@SQLINCLUDE)-1)+')'

               SET @SQLON = @SQLON + @SQLINCLUDE

               PRINT @SQLON

               IF @IFEXEC = '1'

                   EXEC(@SQLON)

           END

       END

 

       FETCH CUR INTO @TB

    END

    CLOSE CUR

    DEALLOCATE CUR

END

go

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章