大家可以看到,执行时间从2秒下降到了0.04毫秒!!!
关于pg的全文检索,tsvector和tsquery,这里就不详细介绍了,大家可以自己查阅手册。
补充:postgresql子查询优化(提升子查询)
问题背景在开发项目过程中,客户要求使用gbase8s数据库(基于informix),简单的分页页面响应很慢。排查发现分页sql是先查询出数据在外面套一层后再取多少条,如果去掉嵌套的一层,直接获取则很快。日常使用中postgresql并没有这样的操作也很快,这是为什么呢?
说明在数据库实现早期,查询优化器对子查询一般采用嵌套执行的方式,即父查询中的每一行,都要执行一次子查询,这样子查询会执行很多次,效率非常低。
本篇主要讲postgresql针对子查询的优化。
项目中使用子查询的地方非常多,如何写出高效的sql,掌握子查询的优化是非常有必要的。
执行计划对比(gbase8s vs postgresql):gbase8s慢sql执行计划:
--gbase8s执行计划
gbase8s修改后执行计划
第一个执行计划中 (1) (Temp Table For Collection Subquery): SEQUENTIAL SCAN)可以看出是将子查询的结果查询出来后,在这个基础上获取了15条记录
对比postgresql执行计划--分页执行计划-不嵌套
postgresql的子查询即使嵌套多层,执行计划还是和未嵌套一样。原因就是postgresql在重写sql的阶段上拉子查询(提升子查询),把子查询合并到父查询中。
postgresql子查询优化子查询可分为三类:一、([not]in/all/any/some),二、([not]exists),三、其他子查询(sjp子查询 选择、投影、连接)
子查询可以出现在目标列、form子句、where子句、join/on子句、group by子句、having子句、orderby子句等位置。
postgresql子链接([not]in,[not]exists,all,some,any)子查询和子链接区别:子查询是不在表达式中的子句,子链接在表达式中的子句
--in子链接
(1).
in子句存在不被优化的可能、当in子句中包含了主查询的表字段,和主查询有相关性时不能提升子链接。
exists子链接--exists子链接
子查询只执行了一次,作为aj表的参数。
从执行计划上看,not exists子查询并没有被消除,子查询只是执行了一次,将结果作为aj表的参数。
in和exists都存在不被优化的可能,对于in和exists的选择,当父查询结果集小于子查询结果集则选择exists,如果父查询结果集大于子查询结果集选择in。
所有的all子链接都不支持上拉关于all的查询都都是以子查询的形式,不会上拉
some/any--some和any是等效的
这些查询中all是完全不支持上拉子子链接的,而in和exists存在不被上拉的可能。
不可上拉的子查询不支持带有with子句的格式,集合操作、聚集函数(aggregates、group、distinct)、cte、having、limit/offset等子句格式
上拉子查询后,父级的多个表之间的连接顺序是怎么样的呢?会有什么变化吗?
对于被上拉的子查询,abase把子查询的关系并入主from-list中,这样关系的个数会增加,按照多表连接顺序算法就会产生更多的连接路径比如A、B、C三张表的关联就有{A,B}、{A,C}、{B,A}、{B,C}、{C,A}、{C,B}六种连接方式
join与子查询固化或rewritejoin或子查询的优化,属于优化器优化JOIN的范畴。
当用户的QUERY涉及到多个JOIN对象,或者涉及到多个子查询时,优化器可以选择是否改变当前的SQL,产生更多的plan选择更优的执行计划。
postgresql.conf文件中:
当from列表的对象少于from_collapse_limit时,优化器可以将子查询提升到上层进行JOIN,从而可能选择到更优的执行计划。
等价改写子查询中没有group by子句,也没有聚集函数,则可使用下面的等价转换
通常,聚集函数min(),max()的执行效率要比any、all效率高
相关子查询和非相关子查询
相关子查询子查询的执行依赖于外层父查询的一些属性值。子查询因依赖于父查询的参数,当父查询的参数改变时,子查询需要根据新参数值重新执行(查询优化器对相关子查询进行优化有一定意义),如:
非相关子查询子查询的执行,不依赖于外层父查询的任何属性值。这样子查询具有独立性,可独自求解,形成一个子查询计划先于外层的查询求解,如:
结束语1.postgresql子查询的优化思路,子查询不用执行多次
2.优化器可以根据统计信息来选择不同的连接方法和不同的连接顺序
3.子查询中的连接条件,过滤条件分别变成了父查询的连接条件、过滤条件、优化器可以对这些条件进行下推、提高执行效率
4.将子查询优化为表连接后,子查询只需要执行一次、而优化器可以根据统计信息来选择不同的连接方式和连接顺序、子查询的连接条件和过滤条件分别变成父查询的条件。
5.这些查询中all是完全不支持上拉子子链接的,in和exists存在不被优化的可能
6.not exists虽然没有被上拉,但是被优化为只执行一次,相对于not in稍好
7.可使用等价改写的方式优化
8.可根据配置文件,固化子查询,以及表的连接顺序
以上为个人经验,希望能给大家一个参考,也希望大家多多支持七叶笔记。如有错误或未考虑完全的地方,望不吝赐教。