zoukankan      html  css  js  c++  java
  • 索引优化--汇总

    思路 :先收集索引的信息,查看已有索引使用情况,删除不使用的索引,合并可以合并的索引,然后再重新收集信息,查看缺失的索引,最后建立索引。

    第一步:收集索引信息

    SELECT o.name AS tableName,
    i.index_id ,
    i.name AS indexName,
    i.type AS indexType,
    i.type_desc AS indexType_Desc ,
    SUBSTRING(ikey.cols, 3, LEN(ikey.cols)) AS key_cols ,
    SUBSTRING(inc.cols, 3, LEN(inc.cols)) AS included_cols ,
    STATS_DATE(o.object_id, i.index_id) AS stats_date ,
    i.filter_definition
    FROM sys.objects o
    JOIN sys.indexes i ON i.object_id = o.object_id
    CROSS APPLY ( SELECT ', ' + c.name + CASE ic.is_descending_key
    WHEN 1 THEN ' DESC'
    ELSE ''
    END
    FROM sys.index_columns ic
    JOIN sys.columns c ON ic.object_id = c.object_id
    AND ic.column_id = c.column_id
    WHERE ic.object_id = i.object_id
    AND ic.index_id = i.index_id
    AND ic.is_included_column = 0
    ORDER BY ic.key_ordinal
    FOR
    XML PATH('')
    ) AS ikey ( cols )
    OUTER APPLY ( SELECT ', ' + c.name
    FROM sys.index_columns ic
    JOIN sys.columns c ON ic.object_id = c.object_id
    AND ic.column_id = c.column_id
    WHERE ic.object_id = i.object_id
    AND ic.index_id = i.index_id
    AND ic.is_included_column = 1
    ORDER BY ic.index_column_id
    FOR
    XML PATH('')
    ) AS inc ( cols )
    WHERE o.type='U' AND i.type IN (1,2)
    ORDER BY o.name ,
    i.index_id

    第二步:收集索引的使用情况

    CREATE TABLE [dbo].[index_usage](
    [DBname] [nvarchar](50) NULL,
    [TableName] [nvarchar](50) NULL,
    [IndexName] [nvarchar](100) NULL,
    [index_id] [int] NULL,
    [TotalWrites] [int] NULL,
    [TotalReads] [int] NULL,
    [Difference] [int] NULL,
    [last_user_seek] [datetime] NULL,
    [last_user_scan] [datetime] NULL,
    [last_user_lookup] [datetime] NULL,
    [last_user_update] [datetime] NULL,
    [RecordTime] [datetime] NULL
    ) ON [PRIMARY]

    -------索引被使用的情况
    INSERT dbo.index_usage
    ( DBname ,
    TableName ,
    IndexName ,
    index_id ,
    TotalWrites ,
    TotalReads ,
    Difference ,
    last_user_seek ,
    last_user_scan ,
    last_user_lookup ,
    last_user_update ,
    RecordTime
    )
    SELECT DB_NAME(ddius.database_id) DBname ,
    OBJECT_NAME(ddius.[object_id]) AS [Table Name] ,
    i.name AS [Index Name] ,
    i.index_id ,
    user_updates AS [Total Writes] ,
    user_seeks + user_scans + user_lookups AS [Total Reads] ,
    user_updates - ( user_seeks + user_scans + user_lookups ) AS [Difference] ,
    ddius.last_user_seek ,
    ddius.last_user_scan ,
    ddius.last_user_lookup ,
    ddius.last_user_update ,
    GETDATE()
    FROM sys.indexes AS i WITH ( NOLOCK )
    LEFT JOIN sys.dm_db_index_usage_stats AS ddius WITH ( NOLOCK ) ON ddius.[object_id] = i.[object_id]
    AND i.index_id = ddius.index_id
    WHERE OBJECTPROPERTY(ddius.[object_id], 'IsUserTable') = 1
    --AND ddius.database_id = DB_ID('MultiCompany')
    --AND OBJECT_NAME(ddius.[object_id]) = 'AccountListOfPaltform'
    AND i.index_id > 1 --非聚集索引
    ORDER BY [Difference] DESC ,
    [Total Writes] DESC ,
    [Total Reads] ASC ;

    第三步:索引使用详情

    CREATE TABLE [dbo].[Index_query_plan](
    [database_name] [nvarchar](max) NULL,
    [TableName] NVARCHAR(max) NULL,
    [OBJECT_NAME] [nvarchar](max) NULL,
    [IndexName] [nvarchar](max) NULL,
    [objtype] [nvarchar](50) NULL,
    [query_plan] [xml] NULL,
    [use_counts] [int] NULL,
    [sql_text] [xml] NULL,
    [RecordTime] [datetime] NULL
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    WITH XMLNAMESPACES(DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')

    INSERT dbo.Index_query_plan
    ( database_name ,
    OBJECT_NAME ,
    objtype ,
    query_plan ,
    use_counts ,
    sql_text ,
    RecordTime
    )
    SELECT COALESCE(DB_NAME(p.dbid)
    , p.query_plan.value('(//RelOp/OutputList/ColumnReference/@Database)[1]','nvarchar(128)'))
    AS database_name
    ,DB_NAME(p.dbid) + '.' + OBJECT_SCHEMA_NAME(p.objectid, p.dbid)
    + '.' + OBJECT_NAME(p.objectid, p.dbid) AS object_name
    ,cp.objtype
    ,p.query_plan
    ,cp.UseCounts AS use_counts
    ,CAST('<?query --' + CHAR(13) + q.text + CHAR(13) + '--?>' AS XML) AS sql_text
    ,GETDATE()
    FROM sys.dm_exec_cached_plans cp
    CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) p
    CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS q
    WHERE cp.cacheobjtype = 'Compiled Plan'
    AND p.query_plan.exist('//RelOp[@Parallel = "1"]') = 1
    ORDER BY COALESCE(DB_NAME(p.dbid), p.query_plan.value('(//RelOp/OutputList/ColumnReference/@
    Database)[1]','nvarchar(128)')), UseCounts DESC

    ----获取使用到有IndexName
    UPDATE A
    SET A.IndexName = CAST(A.query_plan.query('
    declare default element namespace "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    data(//IndexScan/Object/@Index)') AS VARCHAR(MAX)),
    A.tablename=CAST(A.query_plan.query('
    declare default element namespace "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    data(//IndexScan/Object/@Table)')AS VARCHAR(MAX))
    --SELECT CAST(A.query_plan.query('
    -- declare default element namespace "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    -- data(//IndexScan/Object/@Index)
    --') AS VARCHAR(MAX)) IndexName,
    --CAST(A.query_plan.query('
    -- declare default element namespace "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    -- data(//IndexScan/Object/@Table)
    --') AS VARCHAR(MAX)) TableName,*
    FROM Index_query_plan A
    WHERE A.IndexName IS NULL

    然后要优化某一条索引时,可以在存储的表中查询:

    select * from Index_query_plan A
    where A.query_plan.exist('//Object[@Index = "[索引名]"]') = 1

    注意:

    这个语句查询的是XML格式的执行计划,XML是大小写区分的,所以要严格按照索引名(在SSMS中查到的名字)来替换,否则查询不出来

    第四步:缺失的索引

    CREATE TABLE [dbo].[Index_optimize](
    [表] [nvarchar](255) NULL,
    [相等列] [nvarchar](255) NULL,
    [不相等列] [nvarchar](255) NULL,
    [包含列] [nvarchar](max) NULL,
    [总查询次数] [int] NULL,
    [平均百分比收益] [decimal](18, 2) NULL,
    [平均成本] [decimal](18, 2) NULL,
    [可能改进] [decimal](18, 2) NULL,
    [CreateSql] [nvarchar](max) NULL,
    [CreateTime] [datetime] NULL
    ) ON [PRIMARY]

    SELECT *,GETDATE()
    FROM ( SELECT statement AS 表 ,
    equality_columns AS 相等列 ,
    inequality_columns AS 不相等列 ,
    included_columns AS 包含列 ,
    user_scans + user_seeks AS 总查询次数 ,
    avg_user_impact AS 平均百分比收益 ,
    avg_total_user_cost AS 平均成本 ,
    avg_total_user_cost * avg_user_impact * ( user_scans
    + user_seeks ) AS 可能改进 ,
    'CREATE INDEX [IX_' + obj.name + '_'
    + CONVERT(VARCHAR(32), GS.group_handle) + '_'
    + CONVERT(VARCHAR(32), D.index_handle) + ']' + ' ON '
    + [statement] + ' (' + ISNULL(equality_columns, '')
    + CASE WHEN equality_columns IS NOT NULL
    AND inequality_columns IS NOT NULL THEN ','
    ELSE ''
    END + ISNULL(inequality_columns, '') + ')'
    + ISNULL(' INCLUDE (' + included_columns + ')', '') AS Create_Index_Syntax
    FROM sys.dm_db_missing_index_details AS D
    INNER JOIN sys.dm_db_missing_index_groups G ON G.index_handle = D.index_handle
    INNER JOIN sys.dm_db_missing_index_group_stats GS ON G.index_group_handle = GS.group_handle
    INNER JOIN sys.objects AS obj ON obj.object_id = OBJECT_ID([statement])
    AND obj.type = 'U'
    ) X
    --WHERE 表 = '[MultiCompany].[Finance].[AccountListOfPaltform]'
    -- --AND (相等列 LIKE '%ReceiveMethod %' OR 相等列 LIKE '%ReceiptsStatus%')
    -- --AND 包含列 LIKE '%cost%'
    ORDER BY 可能改进 DESC

    原文:https://www.cnblogs.com/binghou/p/9109635.html

  • 相关阅读:
    Add Binary
    Java笔记之String
    Java笔记之数组
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Longest Common Prefix
    Roman to Integer
    Palindrome Number
    Reverse Integer
    _cdel stdcall
  • 原文地址:https://www.cnblogs.com/footleg/p/12204850.html
Copyright © 2011-2022 走看看