Sql server SQL Server非聚集索引设计

Sql server SQL Server非聚集索引设计,sql-server,database,sql-server-2005,indexing,Sql Server,Database,Sql Server 2005,Indexing,这个问题涉及在SQLServer2005中设计非聚集索引 我有一张有几百万行的大桌子。只能读取或插入行。大多数操作都是读操作。我一直在研究访问表的各种SELECT查询,目的是提高读取访问速度。磁盘空间不是一个真正的问题。(每行都有一个唯一的ID,我将其用作聚集索引中的单个字段。) 我的问题是,如果非聚集索引索引的列数大于查询使用的列数,那么这是否会导致查询执行速度比完全匹配查询的索引慢 随着不同查询数量的增加,在其WHERE子句中使用的列排列数量也会增加。我不确定多个索引中列数较少(每个查询一个

这个问题涉及在SQLServer2005中设计非聚集索引

我有一张有几百万行的大桌子。只能读取或插入行。大多数操作都是读操作。我一直在研究访问表的各种
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
  • 柱状
  • 柱状
  • 专栏
  • 专栏
按照这个顺序,查询过滤ColumnA、ColumnB、ColumnC、ColumnD。。。将使用索引,但如果只是查询ColumnE或ColumnF,则不会使用索引

如果在一个表上有六个索引,每个索引只有一列,则采用不同的方法

  • Index1-列
  • Index2-B列
  • Index3-列C
  • Index4-列D
  • Index5-列
  • Index6-ColumnF
在这种情况下,这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; 
选择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;
我通常会找到