索引生成器

索引生成器

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

-- 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

 

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