正确合理使用数据库中的索引Word文档下载推荐.docx
《正确合理使用数据库中的索引Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《正确合理使用数据库中的索引Word文档下载推荐.docx(6页珍藏版)》请在冰豆网上搜索。
select*fromtable1wherefield1<
=10000andfield1>
=0;
select*fromtable1wherefield1>
=0andfield1<
=10000;
如果数据表中的数据field1都>
=0,则第一条select语句要比第二条select语句效率高的多,因为第二条select语句的第一个条件耗费了大量的系统资源。
第一个原则:
在where子句中应把最具限制性的条件放在最前面。
(2)在下面的select语句中:
select*fromtabwherea=…andb=…andc=…;
若有索引index(a,b,c),则where子句中字段的顺序应和索引中字段顺序一致。
第二个原则:
where子句中字段的顺序应和索引中字段顺序一致。
------------------------------------------------------------------------------
以下假设在field1上有唯一索引I1,在field2上有非唯一索引I2。
(3)selectfield3,field4fromtbwherefield1='
sdf'
快
select*fromtbwherefield1='
慢,
因为后者在索引扫描后要多一步ROWID表访问。
(4)selectfield3,field4fromtbwherefield1>
='
selectfield3,field4fromtbwherefield1>
'
慢
因为前者可以迅速定位索引。
(5)selectfield3,field4fromtbwherefield2like'
R%'
selectfield3,field4fromtbwherefield2like'
%R'
因为后者不使用索引。
(6)使用函数如:
selectfield3,field4fromtbwhereupper(field2)='
RMN'
不使用索引。
如果一个表有两万条记录,建议不使用函数;
如果一个表有五万条以上记录,严格禁止使用函数!
两万条记录以下没有限制。
(7)空值不在索引中存储,所以
selectfield3,field4fromtbwherefield2is[not]null不使用索引。
(8)不等式如
selectfield3,field4fromtbwherefield2!
TOM'
相似地,
selectfield3,field4fromtbwherefield2notin('
M'
'
P'
)不使用索引。
(9)多列索引,只有当查询中索引首列被用于条件时,索引才能被使用。
(10)MAX,MIN等函数,使用索引。
Selectmax(field2)fromtb所以,如果需要对字段取max,min,sum等,应该加索引。
一次只使用一个聚集函数,如:
select“min”=min(field1),“max”=max(field1)fromtb
不如:
select“min”=(selectmin(field1)fromtb),“max”=(selectmax(field1)fromtb)
(11)重复值过多的索引不会被查询优化器使用。
而且因为建了索引,修改该字段值时还要修改索引,所以更新该字段的操作比没有索引更慢。
(12)索引值过大(如在一个char(40)的字段上建索引),会造成大量的I/O开销(甚至会超过表扫描的I/O开销)。
因此,尽量使用整数索引。
Sp_estspace可以计算表和索引的开销。
(13)对于多列索引,orderby的顺序必须和索引的字段顺序一致。
(14)在sybase中,如果orderby的字段组成一个簇索引,那么无须做orderby。
记录的排列顺序是与簇索引一致的。
(15)多表联结(具体查询方案需要通过测试得到)
where子句中限定条件尽量使用相关联的字段,且尽量把相关联的字段放在前面。
selecta.field1,b.field2froma,bwherea.field3=b.field3
1.field3上没有索引的情况下:
对a作全表扫描,结果排序
对b作全表扫描,结果排序
结果合并。
对于很小的表或巨大的表比较合适。
2.field3上有索引
按照表联结的次序,b为驱动表,a为被驱动表
对b作全表扫描
对a作索引范围扫描
如果匹配,通过a的rowid访问
(16)避免一对多的join。
如:
selecttb1.field3,tb1.field4,tb2.field2fromtb1,tb2wheretb1.field2=tb2.field2andtb1.field2=‘BU1032’andtb2.field2=‘aaa’
declare@avarchar(80)
select@a=field2fromtb2wherefield2=‘aaa’
selecttb1.field3,tb1.field4,@afromtb1wherefield2=‘aaa’
(16)子查询
用exists/notexists代替in/notin操作
比较:
selecta.field1fromawherea.field2in(selectb.field1frombwhereb.field2=100)
selecta.field1fromawhereexists(select1frombwherea.field2=b.field1andb.field2=100)
selectfield1fromawherefield1notin(selectfield2fromb)
selectfield1fromawherenotexists(select1frombwhereb.field2=a.field1)
(17)主、外键主要用于数据约束,sybase中创建主键时会自动创建索引,外键与索引无关,提高性能必须再建索引。
(18)char类型的字段不建索引比int类型的字段不建索引更糟糕。
建索引后性能只稍差一点。
(19)使用count(*)而不要使用count(column_name),避免使用count(distinctcolumn_name)。
(20)等号右边尽量不要使用字段名,如:
select*fromtbwherefield1=field3
(21)避免使用or条件,因为or不使用索引。
2.避免使用orderby和groupby字句。
因为使用这两个子句会占用大量的临时空间(tempspace),如果一定要使用,可用视图、人工生成临时表的方法来代替。
如果必须使用,先检查memory、tempdb的大小。
测试证明,特别要避免一个查询里既使用join又使用groupby,速度会非常慢!
3.尽量少用子查询,特别是相关子查询。
因为这样会导致效率下降。
一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。
查询嵌套层次越多,效率越低,因此应当尽量避免子查询。
如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。
4.消除对大型表行数据的顺序存取
在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。
比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10亿行数据。
避免这种情况的主要方法就是对连接的列进行索引。
例如,两个表:
学生表(学号、姓名、年龄……)和选课表(学号、课程号、成绩)。
如果两个表要做连接,就要在“学号”这个连接字段上建立索引。
还可以使用并集来避免顺序存取。
尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。
下面的查询将强迫对orders表执行顺序操作:
SELECT*FROMordersWHERE(customer_num=104ANDorder_num>
1001)ORorder_num=1008
虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。
因为这个语句要检索的是分离的行的集合,所以应该改为如下语句:
SELECT*FROMordersWHEREcustomer_num=104ANDorder_num>
1001
UNION
SELECT*FROMordersWHEREorder_num=1008
这样就能利用索引路径处理查询。
5.避免困难的正规表达式
MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。
但这种匹配特别耗费时间。
例如:
SELECT*FROMcustomerWHEREzipcodeLIKE“98___”
即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。
如果把语句改为SELECT*FROMcustomerWHEREzipcode>
“98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。
另外,还要避免非开始的子串。
例如语句:
SELECT*FROMcustomerWHEREzipcode[2,3]>
“80”,在where子句中采用了非开始子串,因而这个语句也不会使用索引。
6.使用临时表加速查询
把表的一个子集进行排序并创建临时表,有时能加速查询。
它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。
SELECTcust.name,rcvbles.balance,……othercolumns
FROMcust