一、因情制宜,建立“适当”的索引
索引(index)是除表之外另一重要的、用户定义的存储在物理介质上的数据结构。当根据索引码的值搜索数据时,索引提供了对数据的快速访问。事实上,没有索引,数据库也能根据SELECT语句成功地检索到结果,但随着表变得越来越大,使用“适当”的索引的效果就越来越明显。注意,在这句话中,我们用了“适当”这个词,这是因为,如果使用索引时不认真考虑其实现过程,索引既可以提高也会破坏数据库的工作性能。
实际上,您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)(相当于汉语词典中的按拼音查询)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)(相当于汉语词典中的俺偏旁部首查询)。每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。
何时使用聚集索引或非聚集索引
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<div align="center"> <table style="width: 80.28%; border-collapse: collapse" cellspacing="0" cellpadding="0" width="80%" border="1"> <tbody> <tr style="height: 17.25pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 17.25pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">动作描述</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 17.25pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">使用聚集索引</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 17.25pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">使用非聚集索引</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">列经常被分组排序</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">返回某范围内的数据</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">一个或极少不同值</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">小数目的不同值</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">大数目的不同值</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">频繁更新的列</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">外键列</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">主键列</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td></tr> <tr style="height: 15pt"> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.1%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">频繁修改索引列</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 27.7%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="27%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">不应</span></p></td> <td style="border-right: #ece9d8; padding-right: 0cm; border-top: #ece9d8; padding-left: 0cm; padding-bottom: 0cm; border-left: #ece9d8; width: 36.2%; padding-top: 0cm; border-bottom: #ece9d8; height: 15pt; background-color: transparent" width="36%"> <p style="line-height: 150%" align="center"><span style="color: black; line-height: 150%; font-family: 宋体">应</span></p></td></tr></tbody></table></div>
索引有助于提高检索性能,但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片。
二、优化SQL语句
(一) select * from TableName where Name='A' and ID>10; select * from TableName where ID>10 and Name='A';这两条语句那条查询速度更快?
SQL SERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。 查询优化器”的工作原理:在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用索引快速获得所需数据。SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的AND连接。形式如下:列名 操作符<常量或变量> 或 <常量或变量>操作符 列名
如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。
介绍完SARG后,我们来总结一下使用SARG以及在实践中遇到的和某些资料上结论不同的经验:
1、Like语句是否属于SARG取决于所使用的通配符的类型
如:name like ‘张%’ ,这就属于SARG 而:name like ‘%张’ ,就不属于SARG。 原因是通配符%在字符串的开通使得索引无法使用。
2、or 会引起全表扫描
Name=’张三’ and 价格>5000 符号SARG,而:Name=’张三’ or 价格>5000 则不符合SARG。
3、非操作符、函数引起的不满足SARG形式的语句
不满足SARG形式的语句最典型的情况就是包括非操作符的语句,如:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE等,另外还有函数。下面就是几个不满足SARG形式的例子: ABS(价格)<5000 Name like ‘%三’ 有些表达式,如:WHERE 价格*2>5000
4、IN 的作用相当与OR
语句:Select * from table1 where tid in (2,3) 和 Select * from table1 where tid=2 or tid=3 是一样的,都会引起全表扫描,如果tid上有索引,其索引也会失效。
5、尽量少用NOT
6、exists 和 in 的执行效率是一样的
7、用函数charindex()和前面加通配符%的LIKE执行效率一样
8、union并不绝对比or的执行效率高
9、字段提取要按照“需多少、提多少”的原则,避免“select *”