我的问题是,如果非聚集索引索引比查询使用的列更多的列,是否会转化为比查询完全匹配的索引更慢的查询执行?
否,具有多个列中的查询时间对于使用在索引中的第一个1,2,n列的查询不会减慢。话虽如此,如果你在内存上受到限制,索引加载到内存中可能会将其他内容推出内存并减慢查询速度,但如果你有足够的内存,这应该不成问题。
随着不同查询的数量增加,其WHERE子句中使用的列的排列数也增加。我不确定使用少量列的索引(每个查询一个索引)与更多列索引较少之间的权衡。
你应该先添加最常查询的唯一字段到索引。 很多列的索引可能不会给你想要的东西。
例如,如果你有以下的列的索引:
- ColumnA
- ColumnB
- ColumnC
- ColumnD
- ColumnE
- ColumnF
,按照ColumnA,ColumnB,ColumnC,ColumnD ...的查询筛选将使用索引,但是如果您只是针对ColumnE或ColumnF查询,它将不会使用索引。
乘坐不同影响的方法,如果你有一个表使用6个索引中的每个只有一列
- 指数1 - ColumnA
- 索引2 - ColumnB
- INDEX3 - ColumnC
- Index4 - ColumnD
- 索引5 - 列E
- 索引6 - 列F
在这种情况下,这6个索引中只有一个将用于任何查询。
另外,如果您的索引包含的值不是很有选择性,那么它可能不会帮助您。例如,如果您有一个名为GENDER的列可能包含以下值(男性,女性和未知),那么它可能不会帮助您将此列包含在索引中。当运行查询时,SQL Server可能会确定它们的列不够具有选择性,只是假定全表扫描会更快。
有许多方法可以找出查询使用的索引,但我使用的一种方法是查看从不使用的索引。在数据库中运行以下查询,并确定您认为正在使用的索引是否真的被使用。
SELECT iv.table_name,
i.name AS index_name,
iv.seeks + iv.scans + iv.lookups AS total_accesses,
iv.seeks,
iv.scans,
iv.lookups,
t.indextype,
t.indexsizemb
FROM (SELECT i.object_id,
Object_name(i.object_id) AS table_name,
i.index_id,
SUM(i.user_seeks) AS seeks,
SUM(i.user_scans) AS scans,
SUM(i.user_lookups) AS lookups
FROM sys.tables t
INNER JOIN sys.dm_db_index_usage_stats i
ON t.object_id = i.object_id
GROUP BY i.object_id,
i.index_id) AS iv
INNER JOIN sys.indexes i
ON iv.object_id = i.object_id
AND iv.index_id = i.index_id
INNER JOIN (SELECT sys_schemas.name AS schemaname,
sys_objects.name AS tablename,
sys_indexes.name AS indexname ,
sys_indexes.type_desc AS indextype ,
CAST(partition_stats.used_page_count * 8/1024.00 AS DECIMAL(10, 3)) AS indexsizemb
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') AS t
ON t.indexname = i.name
AND t.tablename = iv.table_name
--WHERE t.IndexSizeMB > 200
WHERE iv.seeks + iv.scans + iv.lookups = 0
ORDER BY total_accesses ASC;
我一般追查从未被使用,或者SQL服务器重新启动后尚未使用几个月指标,并确定它们是否应该删除或没有。有时,太多的索引可能会减慢SQL Server计算出运行查询的最佳路径的速度,并且删除未使用的索引可以加速该过程。
我希望这有助于理解您的索引。
伟大的问题!这不是一个真正的答案,但是Kimberly Tripp在SQL索引编写方面写了很多精彩的文章,你可能想看看。这里只有一个 - http://www.sqlskills.com/blogs/kimberly/Default.aspx#p4 – Yuck