`

不要迷信所谓的“SQL优化原则”

阅读更多

     

     网上我们经常可以找到大量的关于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中执行时间为7ssql,在应用程序中执行却需要3分钟,随后我们改为非预编译sql,执行时间与在工具中的执行时间相同。(IBatis的配置文件的##全部改为$$,SQL将变为非预编译SQL)。改为非预编译SQL

 

Oraclesharepool不会存储非预编译sql的执行计划了?但是我们可以很清楚的看到在工具中第一次执行sql是比较慢的,第二次执行就会快些。

 

3)      使用索引一定会比全表扫描快吗?

SQL的执行计划是经过DBMS的查询分析器经过比较选取的,根据数据量的不同,数据的不同,会产生不同的执行计划,如果数据量比较小,或者使用索引的Cost还不如全表扫描,那么查询分析器会采用全表扫描。

4)      复合索引如果不使用首列会失效吗?

oracle10g可以使用跳跃索引扫描,如果不使用复合索引的leading column即首列,也是可以使用该复合索引的

5)      索引越多越好吗

索引是消耗存储空间的,索引太多会导致更新或者插入很慢,因为更新或者插入会同时更新插入索引。

6)      在一次select中一个表的多个索引会同时使用吗?

DB2中有多索引扫描,详细请参考牛新庄的《DB2 DBA参考》,其中可以同时使用2个索引,然后对结果集进行合并,在oracle中还没有看到,因此有待考证。在oracle中,一般情况下,对于一个表只会使用一个索引,所以索引不必建立很多优化查询,因为一次查询只能使用一个索引,请大家讨论

7)      使用or连接或者in一定不使用索引吗?

有些帖子讲应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:

select id from t where num=10
union all
select id from t where num=20

实际上对于简单的查询使用orin也是可以使用索引的

分享到:
评论
24 楼 wolfbrood 2011-02-16  
<div class="quote_title">zzhonghe 写道</div>
<div class="quote_div">也谈谈预编译和非预编译的优劣:<br><br>对于执行时间有好几秒的的SQL,从性能的观点出发的话,最好使用非预编译,这样的话,优化器能够根据你传的实际值来制定更加优良的计划。  <br><br>举个例子:<br><br>有个id auto increament的表,有10万条数据。<br><br>非预编译:<br>select * from table where id&lt;10  优化器会让查询走索引, 全表扫是很慢的<br><br>select * from table where id&lt;99990   优化器知道全表扫描更好, 此时走索引要慢很多倍<br><br>而预编译<br>select * from table where id&lt;?<br><br>不管是查10,还是99990,都只有一种执行计划,性能怎么样就只能靠人品了。</div>
<p> </p>
<p>以前我也遇到过的这种情况,在oracle 10g, 它有自己的之下你给计划,现则一跳它认为最好,结果每次都给我选择最慢的。</p>
<p> </p>
23 楼 zzhonghe 2011-02-15  
也谈谈预编译和非预编译的优劣:

对于执行时间有好几秒的的SQL,从性能的观点出发的话,最好使用非预编译,这样的话,优化器能够根据你传的实际值来制定更加优良的计划。 

举个例子:

有个id auto increament的表,有10万条数据。

非预编译:
select * from table where id<10  优化器会让查询走索引, 全表扫是很慢的

select * from table where id<99990   优化器知道全表扫描更好, 此时走索引要慢很多倍

而预编译
select * from table where id<?

不管是查10,还是99990,都只有一种执行计划,性能怎么样就只能靠人品了。
22 楼 sdh5724 2011-02-14  
突然想到一些事情: 总是有人试图证明爱因斯坦是错误的。
21 楼 boylook 2011-02-10  
冲着标题来的。。。看到内容闪了
20 楼 softctwo 2010-05-13  
我就是来顶你一下哈
19 楼 blackchoc 2010-05-13  
不错的主题。如果我们的sql需要被优化,我们肯定会试各种方案。
实践才是正道。
呵呵
18 楼 zhxp791008 2010-05-10  
有兴趣的看下,基于成本的sql优化法则、oracle高性能sql、oracle性能优化内幕等,看了以后写sql就不会迷茫了。
17 楼 whaosoft 2010-05-09  
robertpi 写道
因为这些文档过时了,oracle也在不断进步,不少优化都不需要了。Oracle高手都是通过metalink找资料的。

这样才好吗 程序员会省好多事 更关心与业务逻辑
16 楼 novembersky 2010-05-07  
关于第4点,跳跃式索引扫描9i就已经有了,虽说在没有使用复合索引的首部分(leading portion)时,可以使用子索引扫描,但是如果复合索引的首部分的选择性很高(重复值很少),那性能也会很糟糕,因为这种跳跃式索引扫描本质上是众多子查询的union。总的来说,最好还是使用复合索引的首部分最为where条件为最佳。
15 楼 qingfengjushi1 2010-05-05  
SQL优化时也要考虑Oracle的几种连接模式, NL连接, Hash连接及归并连接的内部处理机制,尽量作到缩小驱动表记录条数,不应该出现几张大表关联的情况。另外cost的值是Oracle判断选择全表扫描或使用索引的依据吧,似乎对优化的作用不大。
14 楼 jiangduxi 2010-05-05  
一看标题,基本上楼主对"sql优化"迷信过,借用一句话,任何事情相信到差不多就可以了,否则就是迷信了。
13 楼 miaow 2010-05-05  
没找到很合适的文档,这个可以参考:
http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/stmtcach.htm

按照该文的说法,要prepared statement发挥作用,恐怕要这样:
压力测试一段时间,保证pool中的connection都cache了相应statement,然后再跑一个压力测试,才能看出有相应效果。

如果是这样,看起来不是问题。
因为有一定负载下效率能提高点,我们在意的也是这情况,看来是值得的。

抱歉当前在折腾DB2,没oracle环境,又不好意思借别人的来压力测试。只好空对空了。
12 楼 miaow 2010-05-04  
有趣。

我承认我没做过性能测试。不过我记得oracle在TopLink的文档中强调过设置statement cache对性能有提高。
毕竟DB和TopLink都是oracle的东西,我相信oracle不会开玩笑吧。

也许和怎么用有关,看看能不能找到进一步文档。
11 楼 liwenjie 2010-05-04  
miaow 写道
怎么觉得很多是老生常谈呢,是有些抄来抄去的网文太老吧

2 我相信有什么地方搞错了,虽然我不认为预编译有什么性能优势,但这个差距显然是有其他地方错了。


另外,常识看是针对谁了,其实对于很多java程序员,不知道数据库这些常识的不少,呵呵。。

请参看下Java Programming with Oracle JDBC: Performance
http://onjava.com/lpt/a/onjava/excerpt/oraclejdbc_19/index.html
有的时候你的“相信”可能不是很准,还是以实验为准

另外,我使用的是oracle 10g 。

sql优化在现在仍然很有用,虽然oracle自己的优化很不错,为什么??就是因为大家初期开发的时候,没有那么注意到性能问题,或者干脆有些程序员不知道如何写出漂亮的sql,导致系统开发后期会有一段专门的时间来优化sql。

可能你使用的是hibernate,可能你不从事ETL,不存在优化长大查询sql的问题,体会不到优化sql的点滴经验教训。

在优化sql的时候,我发现有些程序员有误解,或者很多网文,干脆就是误人子弟,包括JavaEye中的有些博客文章,也是这样的,轻易地得出“什么比什么快”的所谓经验,因此贴出来分享。


总之,在硬件一定的前提下,优化sql还是从实际出发,本着减少IO的大原则,实在不行就进行再次加工,比如水平、垂直切分表,当然这已经不是sql优化的工作了。
10 楼 miaow 2010-05-04  
lookdd1 写道
lz也没说用的是oracle哪个版本的。每个版本对于非预编译优化的也不一样,而且记得tomas说过非预编译的sql会引起latch xxxx的问题。。具体忘记了。。   
还有那个in 据说  (又是据说啊)in里面是个子查询的时候不会使用索引,而具体的值的时候也会应用索引

呃,in那个不见得,oracle的优化器还是满努力的,有时候会优化成相当于把子查询打开、先连接、再筛重复的形式。
9 楼 hotjava 2010-05-04  

现在oracle的自动优化已经作的不错了,除了极少数sql写的实在不好。或者是没加索引。
剩下的都要从设计上去考虑了。执行计划不仅仅要看cost,还要看cardinality和bytes, 都很重要。 多看看oracle的awr日志。

8 楼 lookdd1 2010-05-04  
lz也没说用的是oracle哪个版本的。每个版本对于非预编译优化的也不一样,而且记得tomas说过非预编译的sql会引起latch xxxx的问题。。具体忘记了。。    还有那个in 据说  (又是据说啊)in里面是个子查询的时候不会使用索引,而具体的值的时候也会应用索引
7 楼 miaow 2010-05-04  
怎么觉得很多是老生常谈呢,是有些抄来抄去的网文太老吧

1 是常识,至少对新一点版本的oracle/DB2是

2 我相信有什么地方搞错了,虽然我不认为预编译有什么性能优势,但这个差距显然是有其他地方错了。

3 是常识

4 你是对的,常见错误,用了旧书的就是如此

5 是常识

6 印象oracle也可以,不过没环境没试一下

7 解释or的貌似不多。oracle的select,in后面跟列表会展开为union不是每本书都会讲的么.
6 楼 liwenjie 2010-05-02  
XTU_xiaoxin 写道
嗯,不错。但我还是有点不明白:关于第七点的描述,请问有根据吗?能说说原理吗?

这一点我是看执行计划的,执行计划一般是反映执行路径的,执行计划也不准??我目前还没有发现,oracle的cost如果不进行设置是一般反映IO的而不是时间。

因为从oracle 9.2 以后cost可以通过optimizer_cost_model决定,IO模式下只计算IO代价,CPU模式下两者都计算。v$sql_plan中可以看到相应数据

另外预编译sql和非预编译sql的执行路径会不一样吗??执行路径和编译应该没有关系
5 楼 sdh5724 2010-05-02  
實踐才能出真知, 任何優化原則, 都是指導性原則, 一般性原則, 不存在所謂的必然, 不然, ORACLE也不要搞什麼執行計劃了, 直接做掉就得了。

但是, 你的第二條。 7S V 3MIN  這個差異, 我覺得你沒有追根究底, 這個性能差異應該不是預編譯的引起的性能問題了。 應該是雖然2條SQL , 但是非預編譯獲得了一個較好的執行計劃。  

非预编译SQL,可能導致sharepool崩潰吧。 雖然LZ有不少自己的觀點, 但是, 多測試下, 也許能發現更多的問題。

第七條, 我記得在MYSQL有點效果, 偶然間測試到的。 但是, ORACLE中, IN, OR 其實優化做的比MYSQL好很多, 這2個東西, 說實話是等價的了。

相关推荐

    不要迷信找最好的人,要找最合适的人-马云.JPG

    不要迷信找最好的人,要找最合适的人-马云.JPG

    Hire&Fire专辑【6】:马云:招人不要迷信最好的人,要找最合适的人-马云.JPG

    Hire&Fire专辑【6】:马云:招人不要迷信最好的人,要找最合适的人-马云.JPG

    只给大模型LeetCode编号,也能解题!大模型表现好是源于对训练数据的记忆吗?请不要迷信大模型.pdf

    请不要迷信大模型》 随着人工智能技术的发展,尤其是AI聊天模型如ChatGPT的崛起,人们对其强大功能充满期待,同时也对其背后的机制产生疑问。大模型,如ChatGPT,因其在众多任务中的出色表现,被视为自然语言处理的...

    我打破了迷信作文.doc

    我呼吁每一位读者,如果你的周围还有迷信的人,请不要嘲笑或忽视他们,而应该耐心地引导他们,帮助他们看到迷信背后的真相。因为,每一个打破迷信的个体,都是推动社会向前发展的重要力量。 教育,个人实践和社会...

    液晶市场“屏”成焦点不要过于迷信原装

    一方面,有些消费者过分迷信原装面板,即使在经济条件不允许的情况下,也愿意购买合资品牌的低端产品。但行业人士指出,这并非明智之举,因为合资品牌的低端产品几乎不可能保持面板原装,同时这个价格也足以购买到...

    魏小李windowsphone UI常见问题及性能优化.pdf

    - 不要迷信第三方类库:包括Toolkit等第三方类库可能存在兼容性问题,使用时需谨慎,必要时可自行开发相应功能。 - 应用认证要求:提交应用审核前,应对照WP应用认证要求进行逐条检查,确保应用符合所有要求。 ...

    初中语文文摘社会请君入瓮除迷信

    在浩瀚的历史长河中,迷信一直是困扰人类社会发展的顽疾之一。它不仅扭曲了人们的理性思维,还可能导致错误的行为决策,造成不可挽回的后果。在中国古代,东汉学者郭宗林的故事,为我们提供了一个破除迷信的生动案例...

    百姓网的网速优化之路

    1. **不要迷信别人的成功经验**:百姓网通过实践发现,盲目复制他人经验并不一定适合自己。例如,尽管PageSpeed、Gzip等技术普遍被认为能提升网速,但百姓网的实际测试结果却并不尽如人意,强调了个性化与创新的重要...

    小学政治:相信科学不迷信(教学方案).pdf

    小学政治:相信科学不迷信(教学方案).pdf

    小学政治相信科学不迷信教学设计.docx

    【小学政治相信科学不迷信教学设计】 这是一份专门针对小学政治科目的教学设计文档,旨在帮助学生理解和接受科学知识,摒弃迷信观念。教学设计的核心目标是培养学生的认知、情感和行为三个层面: 1. 认知目标: -...

    《公主的迷信》歌词信.docx

    3. **年轻与迷信**:“你还年轻 你还迷信”,这里的“迷信”是指对理想爱情的盲目追求,相信童话般的爱情故事会在现实中发生,男主角提醒女主角不要过于迷信这些幻想。 4. **王子与幸福**:“梦中的王子在某地总会...

    只给大模型LeetCode编号,也能解题!大模型表现好是源于对训练数据的记忆吗?请不要迷信大模型

    标题中的“只给大模型LeetCode编号,也能解题!...尽管AI在代码生成方面取得了进步,但我们仍需谨慎对待大模型的解题能力,不应过分迷信。在实际应用中,结合人类的专业知识和AI的辅助,可能会产生更好的效果。

    弘扬科学精神反对封建迷信学习教案.ppt

    【标题】:“弘扬科学精神反对封建迷信学习教案.ppt” 【描述】:这份学习教案旨在教育和提升学员对科学精神的理解,同时批判封建迷信,强调科学在现代社会中的重要性。 【标签】:“专业资料” 【内容概述】: ...

    ORACLE学习心得

    Oracle数据库是全球广泛使用的大型企业级数据库管理系统,其性能优化和设计原则对于任何IT专业人员来说都是至关重要的。本文将围绕“ORACLE学习心得”展开,深入探讨Oracle数据库的优化策略、并发控制、数据库设计...

    六年级上册品德14崇尚科学破除迷信反对邪教∣泰山版.pptx

    【崇尚科学,破除迷信,反对邪教】是品德教育中的重要主题,旨在培养孩子们的科学精神和批判性思维,让他们能够辨别事实与虚构,理解科学原理,避免受到迷信思想和邪教活动的影响。以下是对这个主题的详细解读: 1....

    对自由贸易的迷信.doc

    【对自由贸易的迷信】 在经济学领域,自由贸易是一个长期被推崇的理念,尤其在正统的西方经济理论中,自由贸易被认为能够实现资源的最优配置,促进全球经济效率。然而,这种迷信并非无懈可击,实际上,自由贸易政策...

    六年级上册品德114崇尚科学破除迷信反对邪教∣泰山版共28张PPT.pptx

    在六年级的品德教育课程中,有一个至关重要的主题——崇尚科学、破除迷信、反对邪教。通过一系列精心设计的PPT演示,教师们向学生传授科学知识,以理性之光照亮他们的心灵,将迷信的阴霾一扫而空。 首先,课程以...

    青少年应警惕网络迷信.docx

    青少年应警惕网络迷信.docx

    优化工作流程提高工作效率.pptx

    误区二,迷信第三方提供的所谓百度权重值。这类数据并非官方提供,它们只是第三方网站根据自己的算法得出的,实际上的参考价值有限。误区三,将domain查询误认为是反向链接的查询。实际上,domain查询得到的是相关域...

Global site tag (gtag.js) - Google Analytics