is there an accepted ratio of reads to writes that makes an index worthwhile or is it less cut and dried than that?
I am using this:
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
to get an idea of the state of the benefit of my indexes.
At the two ends of the results I am clear - 1,000,000 reads and 0 writes = good index to speed up data retrieval, 1,000,000 writes and 0 reads means we are maintaining an index for zero reference.
What I am not certain on is where the activity is shown as more balanced - where do I make the cut and start dropping indexes?
thanks
Jonathan
I don't think it makes sense to base the decision on the number of reads/writes alone (unless of course you reads==0, but then why do you have the table? :-)).
Consider that:
In short, like always, the only advice is: profile before optimizing. There is no easy shortcut :-/.
What are you trying to achieve? are you trying to improve i/o performance? are you running low on disk space? Premature optimization is the root of all evil!
Stick with the quick wins like 0 reads & 100,000,000 writes. Everything else is a trade off. If your server has headroom, but no disk space, then start working backwards from the lowest ratio of reads to writes and keep an eye on the performance.
It may be wiser to explore other alternatives such as optimizing the procedures/queries, adding page compression, adding disk space/RAM ect.