这是一个系列,主要关于POSTGRESQL 数据库与SQL 有关的优化,目前已经写到了第6篇。
SQL 的执行本身分为几个步骤
1 SQL语句的语法分析,词法的分析
2 语意分析
3 语句重写
4 执行计划优化
5 执行
所以一个SQL 语句从你回车的时刻开始,就需要经历这5个步骤
首先是语法和词法的分析,这里说着好像没有什么难度,但实际上我们通过一个例子就可以明确即时是SQL语句的第一步 语法和词法的分析,也会非常的复杂。下面就是一个简单的SELECT 语句可以带有的参数和词法,此时SQL的第一步关于词法的分析,就从这里开始。
针对需要进行解析的语句种类有
1 select
2 insert
3 update
4 declare cursor
5 create as
6 create materialized view
7 refresh materialized view
8 execute
针对这些操作会将DML 与其他的语句分开,POSTGRESQL 通过操作系统中的工具,Lex与yacc来进行相关的工作,对于SQL中的关键字进行标识,并将其发送给分析器通过分析器里面的语法规则通过触发的方式工作。
语法语义主要的功能将SQL 复杂的语句进行分割,为后续的分析做准备,并且生成将这些信息生成 raw parse tree 解析树作为下一个步骤的输入。
要查询这些可以通过pg_rewrite 来查询,这里有对表和视图的重写记录。下面的内容才是系统接收的查询重写后的东西。
根据系统重写的信息,数据库系统通过优化器将这些信息和本地服务器中的表的统计分析信息综合后产生了关于这个语句的执行计划,这里将逻辑操作转换为物理操作,可能将多个逻辑操作合并为一个物理操作。在构建执行计划的时候,会计算每个操作的成本,最终组合成多个执行的方式并计算总成本,成本最低的为最优选,估算成本的方式CBO,RBO,在可以计算成本的情况下采用通过成本计算的方式形成计划,在没有办法通过成本计算的时候,通过规则的方式形成计算结果。
这里PG通过explain 的方式对执行的语句的执行的评估的计划进行展示,从里到外,从下到上的方式进行执行顺序的展示。
也可以通过pgadmin 来展示图形化的执行计划
这里会产生一个问题,就是早期的或有的数据库对于SQL的写法要求的甚多,这其实就是第一步对于SQL语句重写的功能较弱,对于强悍的数据库系统,SQL语句的多种写法达到的结果一致的情况下,语句的重写会重写成一种方式,这样在后期生成执行计划就会避免一些问题,数据库的优化引擎的工作也会更加准确,而不会造成语句中的条件必须要有顺序的撰写。
这里我们以 full scan , merge sort , hash join 等对多表的算法举例,三个表的关联操作在没有条件的情况下,仅仅是连接的情况下 9 种连接的方式,12种可能的连接顺序,那么整体的执行计划可以考虑的范畴就是 3*3*9 108种,
如果再有一些WHERE条件,分分钟可以突破4位数的执行计划方案。如果其中再有子查询,基于代价的优化算法依赖于最优性原则:最优计划的子计划对于相应的子查询是最优的。一个计划可以被认为是由多个组成部分或子计划组成的。子计划是包含原始计划作为根节点的任何操作及其所有子代节点的计划,也就是说,所有的操作构成了作为子计划的根的操作的输入参数。优化器从最小的子计划(即对单个表的数据访问)开始构建最优计划。这是一件非常耗费计算资源的工作,所以数据库才会缓存执行计划,对同样查询的结构,尽量使用同一种执行计划的方案。
执行计划方案在得出后,的成本计算是下一步,在PG的参数配置中有针对tuple, index 计算, IO性能提取的参数设置,这也是一种开放的心态,信任用户可以在直销自己的硬件性能的基础上,通过调整PG的系统的计算基础成本数据,让SQL在计算的时候充分利用硬件,使用更合适的成本估算的模式。
这也会产生一定的影响,就是用户在不熟悉硬件,以及PG的情况下,不能发挥数据库本身的特性和性能优化特性。
实际中的状况其实更多,下面两个查询的语句仅仅是在条件的值进行了变化,整体的执行计划就变化了。所以查询的条件导致的数据量的变化也是导致你查询时执行计划变化的一个原因,同时在有些数据库中会导致查询中一会快,一会儿慢,这也是数据库本身使用了同一个执行计划,去套用在不同条件的状态,造成的问题。
那么我们追究到底什么原因造成上面的问题,其实有是一个很复杂的问题
你的统计分析的信息是否正确,在正确的情况下会根据你条件数据的的数量来分析你使用INDEX 或者 FULL SCAN 那种方式更有利,最终导致判断COST在不同条件下值的不同。
通常的情况下,数据库都会根据已有的统计分析数据以及自己定义好的CBO来对产生的执行计划进行COST评估,这也是目前大多数商业数据库采用的方案之一。
参考文章
https://www.cnblogs.com/flying-tiger/p/6021107.html
https://www.sqlservercentral.com/articles/getting-a-query-execution-plan-in-postgresql