Sql server SQL Server非聚集索引设计
这个问题涉及在SQLServer2005中设计非聚集索引 我有一张有几百万行的大桌子。只能读取或插入行。大多数操作都是读操作。我一直在研究访问表的各种Sql server SQL Server非聚集索引设计,sql-server,database,sql-server-2005,indexing,Sql Server,Database,Sql Server 2005,Indexing,这个问题涉及在SQLServer2005中设计非聚集索引 我有一张有几百万行的大桌子。只能读取或插入行。大多数操作都是读操作。我一直在研究访问表的各种SELECT查询,目的是提高读取访问速度。磁盘空间不是一个真正的问题。(每行都有一个唯一的ID,我将其用作聚集索引中的单个字段。) 我的问题是,如果非聚集索引索引的列数大于查询使用的列数,那么这是否会导致查询执行速度比完全匹配查询的索引慢 随着不同查询数量的增加,在其WHERE子句中使用的列排列数量也会增加。我不确定多个索引中列数较少(每个查询一个
SELECT
查询,目的是提高读取访问速度。磁盘空间不是一个真正的问题。(每行都有一个唯一的ID,我将其用作聚集索引中的单个字段。)
我的问题是,如果非聚集索引索引的列数大于查询使用的列数,那么这是否会导致查询执行速度比完全匹配查询的索引慢
随着不同查询数量的增加,在其WHERE
子句中使用的列排列数量也会增加。我不确定多个索引中列数较少(每个查询一个)与多个列中索引数较少之间的权衡
例如,假设我有两个
SELECT
查询。第一个在其WHERE
子句中使用A、B、C和D列,第二个使用A、B、E和F。这里的最佳做法是定义两个索引,一个在A/B/C/D上,另一个在A/B/E/F上;还是a/B/C/D/E/F上的单个索引?首先,索引中列的顺序很重要。因此,相应地构建/优化查询将允许您充分利用所构建的索引
是否分别有两个索引或一个索引取决于争用列的依赖关系以及运行的查询类型。在您的示例中,如果E和F列与C和D列相关或依赖于C和D列,那么使用一个索引覆盖所有列是有意义的
我的问题是,如果非聚集索引索引的列数大于查询使用的列数,那么这是否会导致查询执行速度比完全匹配查询的索引慢
不,对于使用索引中前1、2、n列的查询,拥有更多列不会降低查询时间。也就是说,如果您的内存有限,那么将索引加载到内存中可能会将其他内容从内存中挤出并减慢查询速度,但是如果您有足够的内存,这应该不是问题
随着不同查询数量的增加,WHERE子句中使用的列排列的数量也会增加。我不确定多个索引中列数较少(每个查询一个)与多个列中索引数较少之间的权衡
您应该首先将最常查询的唯一字段添加到索引中。
少索引多列可能无法满足您的需要
例如,如果您有一个包含以下列的索引:
- 圆柱
- 专栏B
- 柱状
- 柱状
- 专栏
- 专栏
- Index1-列
- Index2-B列
- Index3-列C
- Index4-列D
- Index5-列
- Index6-ColumnF
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;
选择iv.table\u名称,
i、 名称作为索引名称,
iv.seek+iv.scans+iv.lookup作为总访问量,
四、寻求,
四,扫描,,
iv.查找,
t、 索引类型,
t、 索引
从(选择i.object\u id,
对象名称(即对象id)作为表名称,
i、 索引id,
求和(即用户搜索)为搜索,
总和(即用户扫描)作为扫描,
求和(即用户查找)作为查找
从sys.t表
内部连接sys.dm\u db\u索引\u使用情况\u统计信息i
在t.object\u id=i.object\u id上
按i.object\u id分组,
i、 索引(id)为iv
内部联接sys.i
关于iv.object\u id=i.object\u id
和iv.index_id=i.index_id
内部联接(选择sys_schemas.name作为schemaname,
sys_objects.name作为表名,
sys_index.name作为indexname,
sys_index.type_desc AS indextype,
将(分区_stats.used _page _count*8/1024.00作为十进制数(10,3))转换为indexsizemb
从sys.dm\u db\u partition\u stats partition\u stats
内部联接sys.index sys\u索引
在分区统计上。[object\u id]=sys\u索引。[object\u id]
并且分区_stats.index_id=sys_index.index_id
和sys_index.type_desc'HEAP'
内部联接sys.objects sys\u对象
在系统对象上。[object\u id]=分区统计信息。[object\u id]
内部联接sys.schemas sys\u schemas
在sys\u对象上。[schema\u id]=sys\u schemas。[schema\u id]
和sys_schemas.name'sys')作为t
在t.indexname=i.name上
和t.tablename=iv.table\u name
--其中t.IndexSizeMB>200
其中iv.seek+iv.scans+iv.lookups=0
按总订单访问ASC;
我通常会找到