The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

                  現(xiàn)在SQL2005提供了DTA的工具,大家在去優(yōu)化一個語句時都有意無意的使用此工具所給出的一些優(yōu)化建議。不過它始終是個工具,所給出的優(yōu)化建議很多時候都是使用2005新的索引功能INCLUDE把查詢列表統(tǒng)統(tǒng)包括在一個索引中。因此,每個開發(fā)人員所定義的索引就會存在重復或是很相似的地方。因為索引頁的數(shù)據(jù)比較密集,因此在對包含有索引列的字段做修改操作時,都會去相應的修改包含此鍵值列的索引。理論上對一張表多加一個索引,修改數(shù)據(jù)的速度就會比原來慢1.2倍。因此,這會增加記錄被鎖定的時間,從而也就會影響到查詢的性能。

                但是,如果通過SQL2005提供的幾個與索引相關的視圖,我們不能很方便的觀察出索引所包含的鍵值列和它的包含列是哪些。同時,如果表是分區(qū)表,通過sys.partitions查看總記錄數(shù)時要累加各分區(qū)的行數(shù)。

                   下面的腳本可以組合這些視圖,查詢出對象名稱、對象類型(表或索引視圖)、索引名稱、索引編號、索引類型、是否主鍵、是否唯一、填充度、鍵值字段、包含字段、表的總記錄數(shù)(取各分區(qū)中行的總數(shù))、索引描述,如下圖部分顯示結果所示,這樣就很方便的判斷出哪些索引是重復或相似的:


          對取包含字段時用到了FOR XML PATH這個功能,可以方便的把包含列組織成A,B,C的形式。然后使用CROSS APPLY得出最終的結果。腳本定義如下:


          USE AdventureWorks;
          GO
          DROP INDEX IX_SalesOrderHeader_CustomerID ON Sales.SalesOrderHeader
          GO
          CREATE INDEX IX_SalesOrderHeader_CustomerID ON Sales.SalesOrderHeader(CustomerID)
          INCLUDE(ShipDate,Freight)
          GO

          --sp_helpindex不能反應出包含字段
          EXEC sp_helpindex 'Sales.SalesOrderHeader'
          GO
          --SQL2005下用于診斷索引重復的腳本
          DECLARE @Result TABLE(
              objname            sysname            NOT NULL,
              objtype            char(2)            NOT NULL,
              indexname        sysname            NOT NULL,
              index_id        int                NOT NULL,
              indextype        tinyint            NOT NULL,
              is_primary_key  bit                NOT NULL,
              is_unique        bit                NOT NULL,
              fill_factor        tinyint            NOT NULL,
              IndexKeys        nvarchar(2126)    NOT NULL,
              Included        nvarchar(max)    NULL,
              rows            bigint            NOT NULL,
              IndexDesc        varchar(210)    NULL
          )


          CREATE TABLE #IndexInfo
          (
              IndexName    sysname         NOT NULL,
              IndexDesc    varchar(210)     NULL,
              IndexKeys    nvarchar(2126)     NULL
          )
          DECLARE @objname     sysname

          DECLARE ObjectList CURSOR FAST_FORWARD FOR
              SELECT SCHEMA_NAME(o.schema_id)+'.'+o.name AS objname
              FROM sys.indexes i JOIN sys.objects o ON i.object_id=o.object_id
              WHERE o.type IN('U','V') AND i.index_id IN(0,1)
                  --AND o.object_id=OBJECT_ID(N'Sales.SalesOrderHeader')

          OPEN ObjectList
          FETCH NEXT FROM ObjectList INTO @objname

          WHILE @@FETCH_STATUS = 0
          BEGIN
              INSERT INTO #IndexInfo EXEC sp_helpindex @objname--使用全名稱,防止直接使用表名稱時無法獲取其它架構表的信息
             
              INSERT INTO @Result
               SELECT SCHEMA_NAME(o.schema_id)+'.'+o.name AS objname, o.type AS objtype,
                   i.name AS indexname,i.index_id,i.type AS indextype,i.is_primary_key,i.is_unique,i.fill_factor,
                  t.IndexKeys,
                  c.name AS Included,
                  p.rows,t.IndexDesc
              FROM sys.indexes i
                   INNER JOIN sys.objects o ON i.object_id=o.object_id
                   INNER JOIN #IndexInfo t ON t.IndexName=i.name
                   CROSS APPLY (SELECT SUM(rows) AS rows
                                   FROM sys.partitions p
                                   WHERE p.index_id = i.index_id AND p.object_id = i.object_id
                               ) p
                   CROSS APPLY (SELECT name=STUFF((SELECT N',' + QUOTENAME(y) AS [text()]
                                 FROM (SELECT c.name AS y
                                          FROM sys.index_columns ic
                                              JOIN sys.columns c ON ic.column_id=c.column_id AND ic.object_id=c.object_id
                                          WHERE ic.object_id=i.object_id AND ic.index_id=i.index_id  AND ic.is_included_column=1
                                      ) AS Y
                                 ORDER BY y FOR XML PATH('')), 1, 1, N'')
                               ) c
              WHERE o.object_id=OBJECT_ID(@objname)
                     
              TRUNCATE TABLE #IndexInfo
             
            FETCH NEXT FROM ObjectList INTO @objname
          END

          CLOSE ObjectList
          DEALLOCATE ObjectList

          DROP TABLE #IndexInfo
          SELECT * FROM @Result ORDER BY objname,index_id
          用于SQL2000的腳本:

          --SQL2000下用于診斷索引重復的腳本
          DECLARE @Result TABLE (
              [objname] [sysname] NOT NULL ,
              [indexname] [sysname] NOT NULL ,
              [indid] [smallint] NOT NULL ,
              [IsUnique] [int] NOT NULL ,
              [IndexKeys] [nvarchar] (2126) NOT NULL ,
              [rowcnt] [bigint] NOT NULL ,
              [rowmodctr] [int] NOT NULL ,
              [keycnt] [smallint] NOT NULL ,
              [OrigFillFactor] [tinyint] NOT NULL ,
              [dpages] [int] NOT NULL ,
              [IndexDesc] [varchar] (210) NULL
          )

          CREATE TABLE #IndexInfo
          (
              IndexName    sysname     NOT NULL,
              IndexDesc    varchar(210)     NULL,
              IndexKeys    nvarchar(2126)     NULL
          )
          DECLARE @objname     sysname,
                  @objid        int

          DECLARE ObjectList CURSOR FAST_FORWARD FOR
              SELECT USER_NAME(o.uid)+'.'+o.name AS objname,o.id AS objid
              FROM dbo.sysobjects o JOIN dbo.sysindexes i ON i.id = o.id
              WHERE o.type IN( 'U','V') AND i.indid IN(0,1) AND o.name<>'dtproperties'--用于保存關系圖的系統(tǒng)表
              ORDER BY o.name,o.uid

          OPEN ObjectList
          FETCH NEXT FROM ObjectList INTO @objname,@objid

          WHILE @@FETCH_STATUS = 0
          BEGIN
              INSERT INTO #IndexInfo EXEC sp_helpindex @objname--使用全名稱,防止直接使用表名稱時無法獲取其它用戶表的信息
             
              INSERT INTO @Result
               SELECT USER_NAME(o.uid)+'.'+o.name AS objname, i.name AS indexname, i.indid,
                  CASE WHEN t.IndexDesc LIKE '%unique%' THEN 1 ELSE 0 END AS IsUnique,
                  t.IndexKeys, i.rowcnt, i.rowmodctr, i.keycnt, i.OrigFillFactor, i.dpages,t.IndexDesc
              FROM dbo.sysindexes i
                   INNER JOIN dbo.sysobjects o ON i.id = o.id
                   INNER JOIN #IndexInfo t ON t.IndexName=i.name
              WHERE o.id=@objid
              TRUNCATE TABLE #IndexInfo
             
            FETCH NEXT FROM ObjectList INTO @objname,@objid
          END

          CLOSE ObjectList
          DEALLOCATE ObjectList

          DROP TABLE #IndexInfo
          SELECT * FROM @Result ORDER BY objname,indid

          posted on 2010-09-02 13:39 Eric_jiang 閱讀(566) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫
          主站蜘蛛池模板: 唐海县| 阳东县| 青田县| 永平县| 杭锦后旗| 玉环县| 吉水县| 平乡县| 新巴尔虎左旗| 水富县| 青川县| 南投市| 昌平区| 祁门县| 扶余县| 清丰县| 蒙城县| 九台市| 会宁县| 哈巴河县| 甘德县| 资阳市| 樟树市| 台东市| 丹江口市| 邹平县| 宿迁市| 三原县| 新密市| 湟源县| 西乌珠穆沁旗| 噶尔县| 颍上县| 桑植县| 侯马市| 彝良县| 台东市| 阿勒泰市| 龙岩市| 五华县| 天峨县|