锁定老帖子 主题:不要迷信所谓的“SQL优化原则”
精华帖 (0) :: 良好帖 (11) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-04-26
最后修改:2010-04-26
网上我们经常可以找到大量的关于sql调优的文章和帖子,实际上如果没有真正的实践,可以说这些所谓的经验总结,在实际中不一定总是正确和有效。因此很容易误导初学者,对于某个sql的怎么执行还是要看实际执行计划,下面就大家容易出现的误解做下说明。
1) 连接或者利用子查询或者视图的结果一定不使用索引吗? 不一定,如果join 一个是子查询,一个是物理表,物理表在关联字段建立了索引,也是可以利用索引的,如果子查询或者视图不包含group by,在子查询外的where条件在 有时相当于拿到子查询中。
例如:select field1 from (select filed1 from table)tmp where filed1>1000 实际上相当于select filed1 from table where field1>1000
2) Oracle的预编译SQL与非预编译SQL快吗? 我们会在网上或者课本上翻出预编译sql相对于非预编译sql的优势,例如: 预编译sql防止了SQL注入,不必考虑特殊字符的转译,提高了安全性,而且数据库会将SQL存储到共享池中,以便下次使用。
但是,在项目中,我们发现在plsqldeveloper中执行时间为7s的sql,在应用程序中执行却需要3分钟,随后我们改为非预编译sql,执行时间与在工具中的执行时间相同。(IBatis的配置文件的##全部改为$$,SQL将变为非预编译SQL)。改为非预编译SQL,
Oracle的sharepool不会存储非预编译sql的执行计划了吗?但是我们可以很清楚的看到在工具中第一次执行sql是比较慢的,第二次执行就会快些。
3) 使用索引一定会比全表扫描快吗? SQL的执行计划是经过DBMS的查询分析器经过比较选取的,根据数据量的不同,数据的不同,会产生不同的执行计划,如果数据量比较小,或者使用索引的Cost还不如全表扫描,那么查询分析器会采用全表扫描。
4) 复合索引如果不使用首列会失效吗? 在oracle10g可以使用跳跃索引扫描,如果不使用复合索引的leading column即首列,也是可以使用该复合索引的
5) 索引越多越好吗 索引是消耗存储空间的,索引太多会导致更新或者插入很慢,因为更新或者插入会同时更新插入索引。
6) 在一次select中一个表的多个索引会同时使用吗? 在DB2中有多索引扫描,详细请参考牛新庄的《DB2 DBA参考》,其中可以同时使用2个索引,然后对结果集进行合并,在oracle中还没有看到,因此有待考证。在oracle中,一般情况下,对于一个表只会使用一个索引,所以索引不必建立很多优化查询,因为一次查询只能使用一个索引,请大家讨论。
7) 使用or连接或者in一定不使用索引吗? 有些帖子讲应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: 实际上对于简单的查询使用or和in也是可以使用索引的 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-04-30
F5 执行计划 也不一定准确;
很多语句执行计划快;真正执行却不一定快; 反正 执行计划 也只能算个参考;不能迷信它;很多语句要真正跑过才算 |
|
返回顶楼 | |
发表时间:2010-05-01
分析过的表和索引,特别是建立了直方图的,通常执行计划都比较可信的。如果所有的执行计划都质疑,那开发就太辛苦了。
而且cost并不代表速度,某些情况下进行取舍,大花销一样带来高速度,最终还是要看实际情况再调优。 |
|
返回顶楼 | |
发表时间:2010-05-01
嗯,不错。但我还是有点不明白:关于第七点的描述,请问有根据吗?能说说原理吗?
|
|
返回顶楼 | |
发表时间:2010-05-01
因为这些文档过时了,oracle也在不断进步,不少优化都不需要了。Oracle高手都是通过metalink找资料的。
|
|
返回顶楼 | |
发表时间:2010-05-02
最后修改:2010-05-02
實踐才能出真知, 任何優化原則, 都是指導性原則, 一般性原則, 不存在所謂的必然, 不然, ORACLE也不要搞什麼執行計劃了, 直接做掉就得了。
但是, 你的第二條。 7S V 3MIN 這個差異, 我覺得你沒有追根究底, 這個性能差異應該不是預編譯的引起的性能問題了。 應該是雖然2條SQL , 但是非預編譯獲得了一個較好的執行計劃。 非预编译SQL,可能導致sharepool崩潰吧。 雖然LZ有不少自己的觀點, 但是, 多測試下, 也許能發現更多的問題。 第七條, 我記得在MYSQL有點效果, 偶然間測試到的。 但是, ORACLE中, IN, OR 其實優化做的比MYSQL好很多, 這2個東西, 說實話是等價的了。 |
|
返回顶楼 | |
发表时间:2010-05-02
最后修改:2010-05-02
XTU_xiaoxin 写道 嗯,不错。但我还是有点不明白:关于第七点的描述,请问有根据吗?能说说原理吗?
这一点我是看执行计划的,执行计划一般是反映执行路径的,执行计划也不准??我目前还没有发现,oracle的cost如果不进行设置是一般反映IO的而不是时间。 因为从oracle 9.2 以后cost可以通过optimizer_cost_model决定,IO模式下只计算IO代价,CPU模式下两者都计算。v$sql_plan中可以看到相应数据 另外预编译sql和非预编译sql的执行路径会不一样吗??执行路径和编译应该没有关系 |
|
返回顶楼 | |
发表时间:2010-05-04
怎么觉得很多是老生常谈呢,是有些抄来抄去的网文太老吧
1 是常识,至少对新一点版本的oracle/DB2是 2 我相信有什么地方搞错了,虽然我不认为预编译有什么性能优势,但这个差距显然是有其他地方错了。 3 是常识 4 你是对的,常见错误,用了旧书的就是如此 5 是常识 6 印象oracle也可以,不过没环境没试一下 7 解释or的貌似不多。oracle的select,in后面跟列表会展开为union不是每本书都会讲的么. |
|
返回顶楼 | |
发表时间:2010-05-04
lz也没说用的是oracle哪个版本的。每个版本对于非预编译优化的也不一样,而且记得tomas说过非预编译的sql会引起latch xxxx的问题。。具体忘记了。。 还有那个in 据说 (又是据说啊)in里面是个子查询的时候不会使用索引,而具体的值的时候也会应用索引
|
|
返回顶楼 | |
发表时间:2010-05-04
现在oracle的自动优化已经作的不错了,除了极少数sql写的实在不好。或者是没加索引。 剩下的都要从设计上去考虑了。执行计划不仅仅要看cost,还要看cardinality和bytes, 都很重要。 多看看oracle的awr日志。 |
|
返回顶楼 | |