何时使用聚集索引或非聚集索引
下面的表总结了何时使用聚集索引或非聚集索引(很重要)。
动作描述
|
使用聚集索引
|
使用非聚集索引
|
列经常被分组排序
|
应
|
应
|
返回某范围内的数据
|
应
|
不应
|
一个或极少不同值
|
不应
|
不应
|
小数目的不同值
|
应
|
不应
|
大数目的不同值
|
不应
|
应
|
频繁更新的列
|
不应
|
应
|
外键列
|
应
|
应
|
主键列
|
应
|
应
|
频繁修改索引列
|
不应
|
应
|
1、用聚合索引比用不是聚合索引的主键速度快
2、用聚合索引比用一般的主键作order by时速度快,特别是在小数据量情况下
3、使用聚合索引内的时间段,搜索时间会按数据占整个数据表的百分比成比例减少,而无论聚合索引使用了多少个
4 、日期列不会因为有分秒的输入而减慢查询速度
二、改善SQL语句
1、Like语句是否属于SARG取决于所使用的通配符的类型
原因是通配符%在字符串的开通使得索引无法使用。
2、or 会引起全表扫描
3、非操作符、函数引起的不满足SARG形式的语句
4、IN 的作用相当与OR
5、尽量少用NOT
6、exists 和 in 的执行效率是一样的
7、用函数charindex()和前面加通配符%的LIKE执行效率一样
8、union并不绝对比or的执行效率高
9、字段提取要按照“需多少、提多少”的原则,避免“select *”
10、count(*)不比count(字段)慢
11、order by按聚集索引列排序效率最高
12、高效的TOP
13、同一列中内容的多少执行效率是不一样的
三、实现小数据量和海量数据的通用分页显示存储过程
--
获取指定页的数据
CREATE PROCEDURE pagination3
@tblName varchar ( 255 ), -- 表名
@strGetFields varchar ( 1000 ) = ' * ' , -- 需要返回的列
@fldName varchar ( 255 ) = '' , -- 排序的字段名
@PageSize int = 10 , -- 页尺寸
@PageIndex int = 1 , -- 页码
@doCount bit = 0 , -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0 , -- 设置排序类型, 非 0 值则降序
@strWhere varchar ( 1500 ) = '' -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL varchar ( 5000 ) -- 主语句
declare @strTmp varchar ( 110 ) -- 临时变量
declare @strOrder varchar ( 400 ) -- 排序类型
if @doCount != 0
begin
if @strWhere != ''
set @strSQL = " select count ( * ) as Total from [ " + @tblName + " ] where " + @strWhere
else
set @strSQL = " select count ( * ) as Total from [ " + @tblName + " ] "
end
-- 以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况
else
begin
if @OrderType != 0
begin
set @strTmp = " < ( select min "
set @strOrder = " order by [ " + @fldName +" ] desc "
-- 如果@OrderType不是0,就执行降序,这句很重要!
end
else
begin
set @strTmp = " > ( select max "
set @strOrder = " order by [ " + @fldName +" ] asc "
end
if @PageIndex = 1
begin
if @strWhere != ''
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ " + @tblName + " ] where " + @strWhere + " " + @strOrder
else
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ "+ @tblName + " ] " + @strOrder
-- 如果是第一页就执行以上代码,这样会加快执行速度
end
else
begin
-- 以下代码赋予了@strSQL以真正执行的SQL代码
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ "
+ @tblName + " ] where [ " + @fldName + " ] " + @strTmp + "( [ "+ @fldName + " ] ) from ( select top " + str (( @PageIndex - 1 ) * @PageSize ) + " [ "+ @fldName + " ] from [ " + @tblName + " ] " + @strOrder + ") as tblTmp)" + @strOrder
if @strWhere != ''
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ "
+ @tblName + " ] where [ " + @fldName + " ] " + @strTmp + "( [ "
+ @fldName + " ] ) from ( select top " + str (( @PageIndex - 1 ) * @PageSize ) + " [ "
+ @fldName + " ] from [ " + @tblName + " ] where " + @strWhere + " "
+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder
end
end
exec ( @strSQL )
GO
CREATE PROCEDURE pagination3
@tblName varchar ( 255 ), -- 表名
@strGetFields varchar ( 1000 ) = ' * ' , -- 需要返回的列
@fldName varchar ( 255 ) = '' , -- 排序的字段名
@PageSize int = 10 , -- 页尺寸
@PageIndex int = 1 , -- 页码
@doCount bit = 0 , -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0 , -- 设置排序类型, 非 0 值则降序
@strWhere varchar ( 1500 ) = '' -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL varchar ( 5000 ) -- 主语句
declare @strTmp varchar ( 110 ) -- 临时变量
declare @strOrder varchar ( 400 ) -- 排序类型
if @doCount != 0
begin
if @strWhere != ''
set @strSQL = " select count ( * ) as Total from [ " + @tblName + " ] where " + @strWhere
else
set @strSQL = " select count ( * ) as Total from [ " + @tblName + " ] "
end
-- 以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况
else
begin
if @OrderType != 0
begin
set @strTmp = " < ( select min "
set @strOrder = " order by [ " + @fldName +" ] desc "
-- 如果@OrderType不是0,就执行降序,这句很重要!
end
else
begin
set @strTmp = " > ( select max "
set @strOrder = " order by [ " + @fldName +" ] asc "
end
if @PageIndex = 1
begin
if @strWhere != ''
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ " + @tblName + " ] where " + @strWhere + " " + @strOrder
else
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ "+ @tblName + " ] " + @strOrder
-- 如果是第一页就执行以上代码,这样会加快执行速度
end
else
begin
-- 以下代码赋予了@strSQL以真正执行的SQL代码
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ "
+ @tblName + " ] where [ " + @fldName + " ] " + @strTmp + "( [ "+ @fldName + " ] ) from ( select top " + str (( @PageIndex - 1 ) * @PageSize ) + " [ "+ @fldName + " ] from [ " + @tblName + " ] " + @strOrder + ") as tblTmp)" + @strOrder
if @strWhere != ''
set @strSQL = " select top " + str ( @PageSize ) + " " + @strGetFields + " from [ "
+ @tblName + " ] where [ " + @fldName + " ] " + @strTmp + "( [ "
+ @fldName + " ] ) from ( select top " + str (( @PageIndex - 1 ) * @PageSize ) + " [ "
+ @fldName + " ] from [ " + @tblName + " ] where " + @strWhere + " "
+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder
end
end
exec ( @strSQL )
GO
四、聚集索引的重要性和如何选择聚集索引
1、您最频繁使用的、用以缩小查询范围的字段上;
2、您最频繁使用的、需要排序的字段上。