MSSQL里面建索引的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MSSQL里面建索引的问题相关的知识,希望对你有一定的参考价值。

MSSQL里面的是不是在外键和经常查询用到的列上建索引。
索引就是主要出现在where 中的字段?可是建过之后感觉没怎么变快,是不是只有大容量的时候,优势才会体现?
还有就是在SQL查询语句中如果用substring(A,100) A为ntext型。这样查询的速度和直接查询A表的速度比较呢?

索引一般建在经常用来筛选的列上,用来提高查询速度。
索引不只是用在where子句中。查询优化器会根据你的查询语句选择合适的索引。建了索引后,查询速度没有变得更快,有几种常见的情况:
1. 索引不合适。例如创建了一个索引 在T表的A列和B列上,而where语句作用在只B列上。
select A, B from T where B = 100
查询需要扫描整个表才能找出 B=100的所有记录。而查询优化器会为以下查询利用索引。
select A, B from T where A = 100
2. 索引的选择性比较低,查询优化器不利用索引。
3. 在索引列上应用了函数,如你举的例子substring(A,100),使得索引列A不是SARG(Search Argument),查询优化器也不会利用索引。查询也要扫描整个表。
还有其它方面的情况。。。

尽量去掉不合适的、多余的索引,因为维护索引会影响insert, update,delete语句的效率和占用存储空间。

如果想深入了解索引,推荐你一本书《SQL Server 2005技术内幕 T-SQL查询》。
参考技术A 首先:索引是优化查询用的,所以索引建立在经常作为条件查询的字段上,外键是属于经常作为条件查询的字段。如果基本不会作为Where条件一部分的字段就根本没有必要加索引
其次:如果几个字段固定出现在Where条件语句里,可以将这几个字段建组合索引

MSSQL订阅库索引对齐

  需求如下图:

  

  在原来的架构中是每台web服务器都固定访问某一台数据库服务器,所以就造成了每台数据库订阅服务器上的索引不一致。现在的需求就是要把所有的订阅库上的索引调整为一致,为了就是实现高可用+负载均衡。原因是因为订阅库出现过硬盘故障,导致部分的应用无法访问了。 

  思路比较简单粗暴

    1、把数据库中所有的索引信息提取出来

SELECT OBJECT_NAME(i.[object_id]) tblname  
    , i.name Index_name  
    , i.index_id  
    , i.type_desc Index_Type
    , c.name ColName  
    , ic.index_column_id index_column_id  
    , ic.is_included_column is_included_column  
    , i.is_unique   
    , i.fill_factor   
    , i.filter_definition  
INTO DBName_Index_Align_192_168_10_2_V1
FROM sys.indexes i  
    LEFT OUTER JOIN sys.index_columns ic ON i.index_id = ic.index_id AND ic.[object_id] = i.[object_id]  
    LEFT OUTER JOIN sys.[columns] c ON c.[object_id] = i.[object_id] AND c.column_id = ic.column_id   
ORDER BY OBJECT_NAME(i.[object_id])

    2、匹配所有的索引(这步比较耗时耗力,相当于重新把所有的库做了一次调优)

      2.1、先用192.168.10.2跟192.168.10.3做匹配,把两个库的索引调整成一致

      2.2、再用192.168.10.2跟192.168.10.4做匹配,把在192.168.10.2上的调整同时调整到192.168.10.3上。

      2.3、若是还有更多的订阅库,就一直使用192.168.10.2来作为匹配的对象,把在此数据库上做的调整同时更新更已经匹配过的订阅数据库上。

# 使用以下的代码来匹配
SELECT
* FROM ( SELECT ia.tblname tblname, ia.Index_name, ia.ColName, ia.index_column_id, ia.Index_Type , ia.is_included_column, ia.filter_definition , ia2.tblname cmp_tblname, ia2.Index_name cmp_Index_name, ia2.ColName cmp_ColName, ia2.index_column_id cmp_index_column_id,ia2.Index_Type cmp_Index_Type, ia2.is_included_column cmp_is_included_column, ia2.filter_definition cmp_filter_definition FROM DBName_Index_Align_192_168_10_2_V1 ia FULL JOIN DBName_Index_Align_192_168_10_3_V1 ia2 ON ia.tblname = ia2.tblname AND ia.Index_name = ia2.Index_name AND ia.ColName = ia2.ColName AND ia.index_column_id = ia2.index_column_id AND ia.is_included_column = ia2.is_included_column ) t WHERE ISNULL(t.tblname , t.cmp_tblname) NOT IN (\'索引名称\')   AND ISNULL(t.Index_Type , t.cmp_Index_Type) <> \'HEAP\' ORDER BY ISNULL(t.tblname , t.cmp_tblname), ISNULL(t.Index_name , t.cmp_Index_name) , ISNULL(t.index_column_id , t.cmp_index_column_id)

  注:这种方法虽然实现比较初级的高可用和负载均衡,但存在以下弊端

    1、因为索引必须对齐,所以在部分的订阅库中也建立了一些可能永远都不会访问到的索引,这样会导致空间消耗和索引更新带来的消耗;

    

  以上,如有错谬,请不吝指正。 

以上是关于MSSQL里面建索引的问题的主要内容,如果未能解决你的问题,请参考以下文章

where条件顺序与建索引顺序

MSSQL ColumnStore 索引 - 常规索引的使用

关于MSSQL 全文索引 某些词特别慢的问题

在 MSSQL 中检索列存储索引的正确磁盘空间使用情况

MSSQL 的复合索引和包含索引有啥区别?

MSSQL之八 实现视图与索引