资源描述
Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,11/7/2009,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,SQL优化原则和技巧,撰写人:石霖,SQL优化原则和技巧撰写人:石霖,能使查询加快的途径,索引的引用,SQL的优化,一些函数的使用技巧,能使查询加快的途径索引的引用,索引的引用(1),当插入的数据为数据表中的记录数量的10%以上,首先需要删除该表的索引来提高数据的插入效率,当数据插入后,再建立索引。,索引的引用(1)当插入的数据为数据表中的记录数量的10%以上,索引的引用(2),避免在索引列上使用函数或计算,在where子句中,如果索引是函数的一部分,优化器将不再使用索引而使用全表扫描。如:,低效:,select*from report_sale_account,where hsjj*10 1000;,高效:,select*from report_sale_account,where hsjj 1000/10;,索引的引用(2)避免在索引列上使用函数或计算,在where子,索引的引用(3),尽量避免在索引列上使用not和“!=”和“”,索引只能告诉什么存在于表中,而不能告诉什么不存在于表中,当数据库遇到not 和“!=”和“”时,就会停止使用索引而去执行全表扫描。,索引的引用(3)尽量避免在索引列上使用not和“!=”和“,索引的引用(4),请务必注意,检索中不要对索引列进行处理,如:TRIM,TO_DATE,类型转换等操作,破坏索引,使用全表扫描,影响SQL执行效率,索引的引用(4)请务必注意,检索中不要对索引列进行处理,如:,索引的引用(5),避免在索引列上使用IS NULL和IS NOT NULL,避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引,对于单列索引,如果列包含空值,索引中将不存在此记录;,对于复合索引,如果每个列都为空,索引中同样不存在此记录。如果至少有一个列不为空,则记录存在于索引中,因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引,索引的引用(5)避免在索引列上使用IS NULL和IS NO,索引的引用(6),索引列上“=”代替“”,低效:,select*from report_sale_account where hsjj 10;,高效:,select*from report_sale_account where hajj=10.000000000000001;,索引的引用(6)索引列上“=”代替“”,SQL的优化技巧(1),Where 子句中的连接顺序:oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须写在其他where条件之前,那些可以过滤掉大量记录的条件必须写在where子句的末尾。,SQL的优化技巧(1)Where 子句中的连接顺序:ora,SQL的优化技巧(1),例如,低效:,select*from report_sale_account e,where hsje5000,and dzxl=000001,and 25(select count(*),from report_sale_account,where code=e.code);,高效:,select*from report_sale_account e,where 255000,and dzxl=000001;,SQL的优化技巧(1)例如,SQL的优化技巧(2),删除全表时,用truncate 替代 delete,同时注意truncate只能在删除全表时适用,因为truncate是ddl而不是dml。,例如删除掉一个100万行的数据。,Truncate table report_sale_account;,比delete from report_sale_account;至少快1000倍。,SQL的优化技巧(2)删除全表时,用truncate 替代,SQL的优化技巧(3),尽量多使用commit:,只要有可能就在程序中对每个delete、insert、update操作尽量多使用commit,这样系统性能会因为commit所释放的资源而大大提高。,SQL的优化技巧(3)尽量多使用commit:,SQL的优化技巧(4),用exists替代in,可以提高查询的效率。,低效,SELECT*FROM REPORT_SALE_ACCOUNT,WHERE COM_CODE,NOT IN(SELECT CODE,FROM BASEINFO_GOODS,WHERE DZXL=000001),高效,SELECT*FROM REPORT_SALE_ACCOUNT,WHERE NOT EXISTS,(SELECT CODE FROM BASEINFO_GOODS,WHERE CODE=REPORT_SALE_ACCOUNT.COM_CODE,AND DZXL=000001),SQL的优化技巧(4)用exists替代in,可以提高查,SQL的优化技巧(5),优化group by,提高group by语句的效率,可以将不需要的记录在group by之前过滤掉。,SQL的优化技巧(5)优化group by,SQL的优化技巧(5),例如:,低效:,select dzxl,avg(hsje),from report_sale_account,group by dzxl,having dzxl=000001,or dzxl=000002;,高效:,select dzxl,avg(hsje),from report_sale_account,where dzxl=000001,or dzxl=000002,group by dzxl;,SQL的优化技巧(5)例如:,SQL的优化技巧(5),避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤,这个处理需要排序、统计等操作。如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。,SQL的优化技巧(5)避免使用HAVING子句,HAVIN,SQL的优化技巧(6),有条件的使用union-all 替代 union:这样做效率会提高3到5倍。,SQL的优化技巧(6)有条件的使用union-all 替代,SQL的优化技巧(7),在含有子查询的SQL语句中,要特别注意减少对表的查询,SQL的优化技巧(7)在含有子查询的SQL语句中,要特别注,SQL的优化技巧(7),例如:,低效,SELECT SUM(HSJE)FROM REPORT_SALE_ACCOUNT,WHERE DZXL=(SELECT DZXL,FROM BASEINFO_GOODS,WHERE CODE=0001),AND PP=(SELECT PP,FROM BASEINFO_GOODS,WHERE CODE=0001),高效,SELECT SUM(HSJE)FROM REPORT_SALE_ACCOUNT,WHERE(DZXL,PP)=(SELECT DZXL,PP,FROM BASEINFO_GOODS,WHERE CODE=0001),Update多个Column同样适用于以上的例子。,SQL的优化技巧(7)例如:,SQL的优化技巧(8),SELECT子句中避免使用*,当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用*是一个方便的方法,不幸的是,这是一个非常低效的方法,实际上,ORACLE在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。,SQL的优化技巧(8)SELECT子句中避免使用*,一些函数的使用技巧,虽然在SQL中盲目引用函数会使性能降低,但如果正确使用合适的函数不仅会使SQL可读性加强,并且能对SQL性能得到提高,使复杂的查询能很方便地实现。,一些函数的使用技巧虽然在SQL中盲目引用函数会使性能降低,但,一些函数的使用技巧,举例说明,有如下学生成绩表(表名为TABLE),姓名,分数,张三,78,李四,92,王五,67,赵六,88,钱七,91,陈八,30,一些函数的使用技巧举例说明姓名分数张三78李四92王五67赵,一些函数的使用技巧,我们的需求:,90分或90分以上为优,8089分良,6079分为中,60分以下为差,获得以下数据,姓名,分数,等级,一些函数的使用技巧我们的需求:,一些函数的使用技巧,低效的做法:,Select 姓名,分数,优 From TABLE Where 分数=90,UNION ALL,Select 姓名,分数,良 From TABLE Where 分数=80 and 分数=60 and 分数80,UNION ALL,Select 姓名,分数,差 From TABLE Where 分数60;,一些函数的使用技巧低效的做法:,一些函数的使用技巧,高效的做法:,Select 姓名,分数,decode(sign(分数-90),-1,decode(sign(分数-80),-1,decode(sign(分数-60),-1,差,中),良),优),from table;,一些函数的使用技巧高效的做法:,完,完,
展开阅读全文