是否存在一个可接受的读写比率,使得索引有价值,或者它没有那么简单?
我正在使用这个:
WITH UnusedIndexQuery ( Object_ID, ObjectName, IndexName, Index_ID, Reads, Writes, Rows )
AS ( SELECT
s.object_id ,
objectname = OBJECT_NAME(s.OBJECT_ID) ,
indexname = i.name ,
i.index_id ,
reads = user_seeks + user_scans + user_lookups ,
writes = user_updates ,
p.rows
FROM
sys.dm_db_index_usage_stats s
JOIN
sys.indexes i
ON
i.index_id = s.index_id
AND s.OBJECT_ID = i.OBJECT_ID
JOIN
sys.partitions p
ON
p.index_id = s.index_id
AND s.OBJECT_ID = p.OBJECT_ID
WHERE
OBJECTPROPERTY(s.OBJECT_ID, 'IsUserTable') = 1
AND s.database_id = DB_ID()
AND i.type_desc = 'nonclustered'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
AND p.rows > 10000
),
IndexSizes ( schemaname, tablename, object_id, indexname, index_id, indextype, indexsizekb, indexsizemb, indexsizegb )
AS ( SELECT
sys_schemas.name AS SchemaName ,
sys_objects.name AS TableName ,
sys_objects.[object_id] AS object_id ,
sys_indexes.name AS IndexName ,
sys_indexes.index_id AS index_id ,
sys_indexes.type_desc AS IndexType ,
partition_stats.used_page_count * 8 AS IndexSizeKB ,
CAST(partition_stats.used_page_count * 8 / 1024.00 AS DECIMAL(10,
3)) AS IndexSizeMB ,
CAST(partition_stats.used_page_count * 8 / 1048576.00 AS DECIMAL(10,
3)) AS IndexSizeGB
FROM
sys.dm_db_partition_stats partition_stats
INNER JOIN sys.indexes sys_indexes
ON
partition_stats.[object_id] = sys_indexes.[object_id]
AND partition_stats.index_id = sys_indexes.index_id
AND sys_indexes.type_desc <> 'HEAP'
INNER JOIN sys.objects sys_objects
ON
sys_objects.[object_id] = partition_stats.[object_id]
INNER JOIN sys.schemas sys_schemas
ON
sys_objects.[schema_id] = sys_schemas.[schema_id]
AND sys_schemas.name <> 'SYS'
)
SELECT
[IndexSizes].[tablename] ,
[IndexSizes].[indexname] ,
[IndexSizes].[indextype] ,
[IndexSizes].[indexsizekb] ,
[IndexSizes].[indexsizemb] ,
[IndexSizes].[indexsizegb] ,
UnusedIndexQuery.Reads ,
UnusedIndexQuery.Writes ,
CAST(CASE WHEN [Reads] = 0 THEN 1
ELSE [Reads]
END / CASE WHEN [Writes] = 0 THEN 1
ELSE writes
END AS NVARCHAR(8)) + ':1' AS [Benefit Ratio (Read:Write)] ,
UnusedIndexQuery.[Rows]
FROM
UnusedIndexQuery
INNER JOIN IndexSizes
ON UnusedIndexQuery.object_id = IndexSizes.object_id
AND UnusedIndexQuery.index_id = IndexSizes.index_id
ORDER BY
CASE WHEN [Reads] = 0 THEN 1
ELSE [Reads]
END / CASE WHEN [Writes] = 0 THEN 1
ELSE writes
END ,
reads ,
[Writes] DESC ,
[indexsizemb] DESC
了解我的指数的效益状况。
在结果的两端,我很清楚 - 1,000,000 次读取和 0 次写入 = 良好的索引,可加快数据检索速度,1,000,000 次写入和 0 次读取意味着我们正在维护零引用的索引。
我不确定的是哪里的活动显示得更平衡 - 我应该在哪里进行削减并开始删除索引?
谢谢
乔纳森
答案1
我认为仅仅根据读/写的次数来做决定是没有意义的(当然,除非你的读取次数==0,但那样的话你为什么还需要这个表呢?:-))。
考虑一下:
- 即使读取次数很少,如果没有索引,这些读取也可能非常耗时
- 读取可能比写入更耗时,因此尽管写入性能有所降低,索引仍然是值得的
- 写入性能不一定会受到影响;我认为大多数现代 DBMS 可以延迟更新索引,直到需要更新为止,因此,例如,连续执行许多 INSERT 操作只会导致一次索引更新
简而言之,一如既往,唯一的建议是:优化之前先进行分析。没有简单的捷径 :-/。
答案2
你想实现什么?你想提高 I/O 性能吗?你的磁盘空间是否不足?过早优化是万恶之源!
坚持快速取胜,例如 0 次读取和 100,000,000 次写入。其他一切都是权衡。如果您的服务器有空间,但没有磁盘空间,那么从最低的读取与写入比率开始向后工作并密切关注性能。
探索其他替代方案可能更明智,例如优化程序/查询、添加页面压缩、添加磁盘空间/RAM 等。