首页 > Linux操作系统 > Linux操作系统 > SQL与优化器的微妙关系
关系型数据库只能通过执行SQL语句来处理数据,如果对SQL语句进行定义,那么它也只不过是为了表达用户的要求而使用的一系列字符而已,它并不像其他编程语言那样必须在编译之后才能执行,SQL语句在被执行之后立刻就可以获得结果。
SQL语句之所以能够被这样执行,主要是因为优化器能够为SQL语句制定出具体的执行步骤,并将其转换为可以执行的模块,在实际的运行结束之后直接返回最终结果。因此从某种意义上来看,用户所要做的事情只不过是提出自己的要求而已,而真正意义上的应用程序则是优化器所创建的执行计划。
由于在执行数据查询时SQL语句是按照执行计划中所定义的步骤来执行的,所以执行计划的合理与否对执行速度有着极大的影响。制定执行计划是优化器的本职工作,它在制定执行计划时不可能凭空想象,毫无根据地随意寻找出逻辑上根本不存在的处理方法,它必须坚持实事求是、一切从实际出发的原则,依据所拥有的各种要素判断出最有利的查询路径。
我们知道,符合逻辑的查询路径会随着各种影响要素的变化而变化。能够影响执行计划的要素不仅仅只有索引和聚簇,而且还有优化器的模式、搜集到的统计信息、SQL语句的形态、系统及网络的状态、优化器的版本等。因此,在决定执行路径时只有对这些影响要素进行综合评估后才能制定出最优化的执行计划。
像我们在第2章“索引的类型和特征”中所介绍的那样,现有索引或者聚簇的使用情况不仅会随着列和运算符号的变化而变化,而且还会随着WHERE条件中所使用的值是常数还是变量的不同而不同。而且即使对于相同的SQL语句,执行计划也会随着WHERE条件中所使用的常数值的离散程度的不同而不同;不仅如此,执行计划还会随着聚簇、表、索引等统计信息的搜集周期、生成时间,生成与否的不同而不同。
在优化器制定执行计划时,所参考的统计信息也会随着DBMS或优化器版本的不同而有所不同。虽然优化器所能够参考的统计信息种类有很多,但是其中对选择最优查询路径影响最大的只有列的离散程度和聚簇因子。换言之,它们将决定着我们是否能够以最少量的数据读取、最少的代价支出来完成数据的处理工作。
尽管优化器的内部机制很复杂,但是它的最终目标是选择一条能够让驱动范围(Driving Range)得到最大程度缩减的路径,以及以最低廉的传输成本(以最少的数据块读取来获得尽可能多的满足查询条件的数据)来读取数据。由于我们不能认为优化器所选择的路径永远都是最优的,所以在开始执行查询之前需要对其进行判断。
不论在任何情况下,只要以离散程度比较好的列作为驱动查询条件,立刻就可以在很大程度上缩小查询范围。事实上,是否按照最优化的方式进行数据查询,与所要查询的数据范围之间没有必然的联系,所以并不是说查询范围小就一定是按照最优的方式进行了查询,在小范围中查询数据的速度之所以快,主要是因为数据量小,所占用的数据块数量也会比较少。对于同样的数据处理要求、同样的环境,如果能够按照本书后面所要介绍的局部范围扫描方式进行处理,问题就会发生质的变化。
由于最优化路径的选择过程其实就是一种仿真的过程,所以优化的结果自然也会随着最优化目标的不同而不同了。从以最快速度返回第一个结果为目标的仿真所获得的结果,尽管与从以整体数据处理最优化为目标的仿真中所获得的结果有所不同,但并不是始终不同。
由于在大部分情况下,把最小的查询范围作为驱动来使用都更为有利,所以如何做才能让查询范围达到最小就成了问题的关键。通过对相关要素(WHERE条件中所出现的列的索引组合、比较运算符、条件中的常数或变量)进行分析之后,如果选择了具有最小查询范围的执行路径,就能够按照我们所期望的最优化执行路径来处理数据。
从上面这句话的意思来看,就好像我们把选择最优路径的重任托付给了优化器一样。但事实并非如此,作为用户的我们在最优路径的选择过程中所起到的作用其实要比优化器大。因为就像我们在前面所说的那样,查询范围大小会随着查询条件的类型、索引的构成类型、聚簇的使用与否等要素的不同而不同。因此作为用户的我们应该将有可能出现的情况进行比较,归纳总结出究竟创建什么样的索引类型、什么样的聚簇类型才能在最大程度上缩减查询范围。
有时优化器也可能制定出出乎我们意料之外的执行计划,当然这种意外也只是偶尔出现。导致发生这种意外的原因既有可能是DBMS的错误,也有可能是优化器没有充分地参考统计信息。由此可见,执行计划是否最优会随着优化器对统计信息的参考程度的不同而不同。
相信很多读者应该非常熟悉黑白逻辑的概念,在很多情况下对于比较难以决定的问题可以使用黑白逻辑理论来帮助解决。那么如果是黑白逻辑所无法解决的问题,不论我们选择哪一边,相对而言都会对另一边不利,如果要求我们必须在两者之间做出一个选择的话,那应当如何选择呢?当然对于我们而言,最理想的办法自然是选择对两方都比较有利的方案了,然而实施起来却并非易事。
同样因为优化器所决定出的执行计划并不是在所有的情况下都比较有利,所以优化器也经常会遇到进退两难的尴尬局面。也许有时优化器能够制订出让人惊讶的执行计划,我们会认为它非常聪明;但也许有时它会制订出出人意料的执行计划,我们就会认为它像一个傻瓜。
在使用关系型数据库的情况下,无论如何都无法避免优化器所带来的影响。如果对优化器没有一个正确且深刻的理解,不论岁月如何流逝,经验如何积累都不可能有大的发展。来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25708791/viewspace-694254/ ,如需转载,请注明出处,否则将追究法律责任。