【问题标题】:MSSQL: Does last_user_update mean that the index hurt performance?MSSQL:last_user_update 是否意味着索引会损害性能?
【发布时间】:2009-06-01 09:56:42
【问题描述】:

我编写了一个查询来查找在生产环境中未使用的索引以删除它们,但是我很好奇 last_user_update 列是否表明索引只是维护开销,在这种情况下最好删除它,或者索引是否有助于插入/更新/删除语句的性能,在这种情况下我不想删除它。以下是我想使用的查询:

DECLARE @DBInfo TABLE  
( database_id int, object_id int, tablename nvarchar(200), indexname nvarchar(200), lastactivity datetime)  

DECLARE @command VARCHAR(5000)  

SELECT @command = 'Use [' + '?' + '] SELECT  
database_id, o.object_id, o.name, i.name as indexname, max(lastactivity) as lastactivity
from (
    select database_id, object_id, index_id, max(last_user_seek) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id
    UNION ALL
    select database_id, object_id, index_id, max(last_user_scan) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id
    UNION ALL
    select database_id, object_id, index_id, max(last_user_lookup) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id
    /*UNION ALL
    select database_id, object_id, index_id, max(last_user_update) as lastactivity from sys.dm_db_index_usage_stats
    WHERE object_id > 1000
    GROUP BY database_id, object_id, index_id*/
) a
inner join sys.objects o on a.object_id = o.object_id
inner join sys.indexes i on i.object_id = a.object_id AND i.index_id = a.index_id
where database_id = db_id()
GROUP BY database_id, o.object_id, o.name, i.name
order by lastactivity'  
INSERT INTO @DBInfo  
   (database_id, object_id, tablename, indexname, lastactivity)  
EXEC sp_MSForEachDB @command  

SELECT db_name(database_id) as dbname, tablename, indexname, lastactivity FROM @DBInfo
where lastactivity < dateadd(day, -15, getdate()) or lastactivity is null
order by db_name(database_id), tablename, indexname 

【问题讨论】:

    标签: sql-server performance maintenance


    【解决方案1】:

    该列在检查未使用的索引时没有任何实际意义。

    索引可能没有最近的更新,但仍然非常有用(例如,避免表扫描或覆盖流行的查询)。此查询告诉您如何使用索引:

    SELECT
        o.name AS [object_name], 
        i.name AS index_name, 
        i.type_desc, 
        u.user_seeks, u.user_scans, 
        u.user_lookups, u.user_updates,
        o.type
    FROM
        sys.indexes i
        JOIN
        sys.objects o ON i.[object_id] = o.[object_id]
        LEFT JOIN 
        sys.dm_db_index_usage_stats u ON i.[object_id] = u.[object_id] AND 
                                        i.index_id = u.index_id AND 
                                        u.database_id = DB_ID()
    WHERE
        o.type IN ('U', 'V') AND
        i.name IS NOT NULL
    ORDER BY 
        o.name, i.NAME;
    

    评论后编辑:

    我更喜欢告诉我如何使用索引的user_seeks, user_scans, user_lookups and user_updates 列。仅供参考,我使用了上面的查询并包含了“system_updates”列,但所有值都为零(SQL 2005,50Gb 左右的数据库,我们之前使用过这个效果很好)

    来自sys.dm_db_index_usage_stats

    user_updates 计数器指示 指数的维护水平 由插入、更新或删除引起 对基础表的操作或 看法。您可以使用此视图 确定仅使用哪些索引 轻轻地通过您的应用程序。你可以 也使用视图来确定哪个 索引正在进行维护 高架。您可能要考虑 删除导致的索引 维护开销,但未使用 用于查询,或者只是偶尔 用于查询。

    所以,最后一句话意味着要查看使用情况和更新情况

    【讨论】:

    • 感谢您的评论。我想 user_updates 专栏提出了同样的问题:它是坏的还是好的? user_updates 对数据修改的性能有帮助还是有损?
    • 添加了更多信息。没有真正使用过这个专栏:我们主要看使用情况。
    【解决方案2】:

    如果您对索引的 动态 属性感兴趣 - 无论它们是否被使用 - 您最好在 DMV 中查询 - Dynamic Management Views。它们应该为您提供有关正在使用哪些索引以及使用频率的详细信息。

    此外,还有一个 DMV 实际上使用查询优化器的内部统计信息来建议 a) 可能有助于提高性能的可能丢失的索引,以及 b) 另一个显示可能未使用的索引。

    请注意 - 这些是动态管理视图 - 它们会在每次服务器重新启动时重置,因此它们不会在永恒的时间段内收集数据 - 仅在您上次重置之后。

    马克

    查找缺失的索引:

    SELECT  
        object_name(object_id), d.*, s.*
    FROM
        sys.dm_db_missing_index_details d 
    INNER JOIN 
        sys.dm_db_missing_index_groups g ON d.index_handle = g.index_handle
    INNER JOIN 
        sys.dm_db_missing_index_group_stats s ON    g.index_group_handle = s.group_handle
    WHERE   
        database_id = db_id()
    ORDER BY  
        object_id
    

    查找未使用的索引:

    DECLARE  @dbid INT
    
    SELECT @dbid = DB_ID(DB_NAME())
    
    SELECT   
        OBJECTNAME = OBJECT_NAME(I.OBJECT_ID),
        INDEXNAME = I.NAME,
        I.INDEX_ID
    FROM     
        SYS.INDEXES I
    JOIN 
        SYS.OBJECTS O ON I.OBJECT_ID = O.OBJECT_ID
    WHERE    
        OBJECTPROPERTY(O.OBJECT_ID, 'IsUserTable') = 1
        AND I.INDEX_ID NOT IN (SELECT S.INDEX_ID
                                FROM SYS.DM_DB_INDEX_USAGE_STATS S
                                WHERE S.OBJECT_ID = I.OBJECT_ID
                                        AND I.INDEX_ID = S.INDEX_ID
                                        AND DATABASE_ID = @dbid)
    ORDER BY 
        OBJECTNAME,
        I.INDEX_ID,
        INDEXNAME ASC
    

    【讨论】:

      猜你喜欢
      • 2018-07-25
      • 2015-06-21
      • 2022-09-23
      • 2014-08-15
      • 2011-10-13
      • 2016-07-20
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多