postgresql 执行计划理解

首先看下postgresql 执行计划中的一些术语和关键字。

执行计划运算类型 操作说明 是否有启动时间
Seq Scan 扫描表 无启动时间
Index Scan 索引扫描 无启动时间
Bitmap Index Scan 索引扫描 有启动时间
Bitmap Heap Scan 索引扫描 有启动时间
Subquery Scan 子查询 无启动时间
Tid Scan ctid = …条件 无启动时间
Function Scan 函数扫描 无启动时间
Nested Loop 循环结合 无启动时间
Merge Join 合并结合 有启动时间
Hash Join 哈希结合 有启动时间
Sort 排序,ORDER BY操作 有启动时间
Hash 哈希运算 有启动时间
Result 函数扫描,和具体的表无关 无启动时间
Unique DISTINCT,UNION操作 有启动时间
Limit LIMIT,OFFSET操作 有启动时间
Aggregate count, sum,avg, stddev聚集函数 有启动时间
Group GROUP BY分组操作 有启动时间
Append UNION操作 无启动时间
Materialize 子查询 有启动时间
SetOp INTERCECT,EXCEPT 有启动时

例子,查询1

explain analyze select r.*,a.username  from t_portal_resource r 
left join t_uc_account a on r.userid=a.id where  r.id in (select resourceid 
from t_portal_cate_res where categoryid in (1)) 
and ( r.title like '%低调%' or r.tags like '%net%' )  order by istop desc, r.id desc limit 10 offset 0

这里explain后加analyze来通过真实执行这个SQL来获得真实的执行计划和执行时间。

postgresql查询计划是按照成本计算的,也就是基于成本的查询计划(cost-based plan),其中影响成本计算的参数包括(后面括号的值为其缺省值):

  • cpu_index_tuple_cost (0.005)
  • cpu_operator_cost (0.0025)
  • cpu_tuple_cost (0.01)
  • random_page_cost (4.0)
  • seq_page_cost (1.0)

    从第一行起,主要查看 cost。 例如上面 cost=11.61..11.61。cost=说明:第一个数字11.61表示启动cost,这是执行到返回第一行时需要的cost值。第二个数字11.61表示执行整个SQL的cost

    actual time=0.183..0.191 rows=3 loops=1。actual time=中的第一个数字表示返回第一行需要的时间(叫启动时间),第二个数字表示执行这个整个花的时间。后面的rows=3是实际的行数。

一个查询的总代价包括读取数据的I/O代价和其他各种操作的代价之和。 I/O代价包括顺序读取数据或索引页(seq_scan_cost)和随机读取数据页(random_scan_cost)的代价,操作代价包括处理表元组(cpu_tuple_cost)、处理比较操作(cpu_operator_cost)和处理索引元组(cpu_index_tuple_cost)。

比如,如果在一个表上做全表顺序扫描,那么其代价公式为:

    Cost = seq_scan_cost*relpages + cpu_tuple_cost*reltuples

如果是在一个表上做全表顺序扫描并执行过滤,则代价公式为:

    Cost = seq_scan_cost*relpages + cpu_tuple_cost*reltuples + cpu_operator_cost*reltuples

对于预算要返回的行数量,其计算公式为:

    rows = reltuples*估算频率

这里,估算频率通过sys_stats视图中统计的列值和出现频率计算得出

relpages磁盘页,reltuples是行数(与实际不一定相符,一般略小)
select relpages,reltuples from pg_class where relname = 't_portal_resource'; 可以查看对象的详细信息pg_class中的relpages,reltuples数据不是实时更新的,一般在vacuum analyze和少部分DDL(如建立索引)后更新。

优化需要查看的系统表: 
    pg_stats 
    pg_statistic 
    pg_class 
    pg_stat是任何人都可以看的,而且可读性高,比较直观,pg_statistic只有superuser才能读,并且可读性差,普通人员建议看pg_stats,pg_stats是pg_statistic的视图。 这两个表也不是实时更新的,需要vacuum analyze时会更新 
所涉及的系统变量: 
    default_statistics_target 
    geqo_threshold 
    join_collapse_limit 
    from_collapse_limit

可以通过 explain 加参数查看更详细的信息,

    ANALYZE :执行命令并显示执行事件,默认false 
    VERBOSE :对执行计划提供额外的信息,如查询字段信息等,默认false 
    COSTS :显示执行计划的,默认true 
    BUFFERS :默认false,前置条件是analyze 
    FORMAT :默认格式是text 

explain (analyze,verbose,costs,buffers) select ...

更详细的资料可以查看这里

我将上面的sql 修改了一下。查询2

explain analyze select r.*,a.username  from t_portal_resource r 
left join t_uc_account a on r.userid=a.id left join (select resourceid 
from t_portal_cate_res where categoryid in (1)) t on r.id=t.resourceid where 
(r.title like '%低调%' or r.tags like '%net%') order by istop desc, r.id desc limit 10 offset 0
将第一个in 语句改为左连接,小表查询,减少了连接的次数,性能有了明显提高:


一般来说sql 中的连接 join 对应在查询计划里有下面几种

  • 嵌套循环连接(Nested loop join)
    • 带内表顺序扫描
    • 带内表索引扫描
  • 合并连接(Merge join)
  • 哈希连接(Hash join)
可以看到,在查询2中,有nested loop left join 连接,但当我把 sql where 条件去掉后,sql 语句中的连接对应在查询计划中都变成了 hash连接,而且性能差很多,因此尽量在有join的多表查询中 包含where 条件,  查询3:



explain analyze select r.*,a.username  from t_portal_resource r 
left join t_uc_account a on r.userid=a.id left join (select resourceid 
from t_portal_cate_res where categoryid in (1)) t on r.id=t.resourceid  order by istop desc, r.id desc limit 10 offset 0


那么什么时候会参数合并merge join 呢。many-to-many 的查询,例如t_portal_cate_res(resourceid,categoryid) 和 t_portal_cate_user(categoryid,userid)

查询4

explain analyze select rs.resourceid from t_portal_cate_res rs 
 left join t_portal_cate_user ca on rs.categoryid=ca.categoryid

但是当把查询4 加上where条件后 where ca.userid=1. 就会变成nest loop 查询。

所以在many-to-many 的表连接查询的时候尽量转换为小表 one-to-many 查询,加上where 条件等等方式优化sql。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引言 欢迎来到PostgreSQL数据库从入门到精通。 在我们生涯的早期,我们开始理解开源软件的质量。不仅通常情况下它们可以自由使用,而且它们提供极高的质量。如果你发现问题,你可以检查源代码,理解程序工作过程。如果你找到一个错误,你可以自己修复或找别人帮你修复。我们从1978年开始试用开源软件,包括优秀的GNU工具,包括GNU Emacs和GCC。我们从1993年开始使用Linux并愉快地使用Linux内核和GNU工具建立了一个完整的,自由的计算环境,并且使用X Window系统提供了一个图形用户界面。PostgreSQL是一个采取相同的开源理念的优秀的数据库系统(更多关于开源和自由的信息,请访问http://www.opensource.org)。 数据库是非常有用的东西。很多人发现“桌面数据库”在办公室和家里的小应用程序中非常有用。很多网站是数据驱动的,很多内容都由网页服务器后面的数据库提供。随着数据库的普及,我们觉得有必要写一本书介绍数据库理论和实践。 我们写这本书整体介绍数据库,全面覆盖现代的关系数据库的能以及怎么高效使用它们。使用 PostgreSQL作为他的数据库的人都没有觉得PostgreSQL在哪方面有什么不足。它支持优秀的数据库设计,非常有弹性和扩展性,且运行在几乎你所能想到的计算机上,包括Linux,Unix,Windows,Mac OS X,AIX,Solaris以及HP-UX。 对了,免得你好奇,我告诉你PostgreSQL念做“post-gres-cue-el”(而不是“post-gray-ess-cue-el”)。 本书大致分为三部分。第一部分包括入门,包括数据库概述(它们是什么以及它们用来干什么),尤其是PostgreSQL的概述(怎样获得,安装和启动以及使用)。如果你同时运行了示例,到第5章完成的时候,你将建立起第一个可工作的数据库并且可以使用一些工具来做一些有用的事情,例如输入数据和执行查询。 本书的第二部分深刻地探索关系数据库的核心:SQL查询语言。通过示例程序和“做一个尝试”章节,你将学到数据库编程的很多方面。,从简单的数据插入和修改,强大的各类查询到通过存储过程和触发器扩展数据库功能。本章最重要的内容是数据库无关,所以你从本章获取的知识能够让你在使用其他数据库时如鱼得水。当然,所有的用来说明的示例资源是用PostgreSQL来作为示例数据库。关于PostgreSQL的管理和数据库设计的习惯用法也将在本章完整讨论。 本书的第三部分关注于在你的程序中发挥PostgreSQL的能力。本章涵盖了通过大量的编程语言连接到数据库、执行查询以及处理结果集。无论你是使用PHP或者Perl开发动态网页、用Java或者C#开发企业级应用程序或者用C写一个客户端程序,你将找到你想要的章节。 这是PostgreSQL从入门到精通的第二版;第一版在2001年发布。从那时起,每章的内容都根据8.0版本的PostgreSQL做了升级。我们在本书中有机补充了新的一章
PostgreSQL简介:MS Sqlserver、Sybase、Informix等多种数据库的起源均可追溯至数据库大师Michael Stonebreaker的Ingres项目。Stonbreaker大师在离开Informix CEO的位置后,启动了Ingres的后续项目,这就是Postgresql,这是具有正统高贵血缘的开源数据库系统,在今天以性能稳定和高度开放著称。在Oracle收购Mysql后,业内人士担心Mysql被闭源,逐渐将应用迁移到其它的数据库选择上,PostgreSQL是一项很好的选择,它具备商业数据库几乎所有的特性,高度支持SQL语言,对开发人员友好,它的过程语言pgsql和Oracle的PLSQL是如此相像,以致于迁移应用几乎不用作过多的修改。今天Postgresql的应用越来越广泛,正在快速蹿红。目前国内对PostgreSQL的使用,主要反映在两个范畴1 用于取代MySQL和Oracle2 作为数据库产品原型,通过修改源码构筑自己的数据库,例如通过使用pgsql解析器,省去自己编写sql解析器的困难。某些拿了政府大量补贴的“国产数据库”软件就是这么干的(在这里就不揭穿是哪家了^_^),EMC的分布式关系式数据库Greenplum就是基于pg,加入分布式处理后脱胎换骨所成。课程概述:像编写数据库的人一样理解Postgresql的实现,让我们这些具有聪明的头脑的人更容易、更简单的运用数据库技术,可以从开发角度掌握扩展数据库功能的设计实现,让我们徜徉在Postgresql的世界。本次课程是构建在一个公司要封装发展自有版本的Postgresql数据库的背景上,用真实项目迁移到Postgresql而对数据库做的改进的工作为蓝本,课程为你讲述Postgresql实现,讲述实际项目应用对Postgresql改进需的过程。课程为了同学更容易掌握Postgresql数据库,特意安排了六周的Postgresql使用课程,让从未接触过Postgresql的同学可以顺利上手使用该数据库,做到了循序渐进。课程目标:掌握Postgresql数据库使用,掌握功能扩展二次开发。授课对象:熟悉数据库原理,Linux使用,C/C++语言。对开源数据库Postgresql感兴趣。预期收获:学Postgresql的使用。在源码级上了解PostgreSQL。知道Postgresql如何实现,从而获得相关数据库内核研发的机。能力提升对C++的掌握,掌握在socket、IO、memory、Thread方面在Linux环境下的编程。对数据库引擎开发工作有一定的认识,能够融入数据库应用的方方面面。是SQL开发工程师、DBA升级成为架构师的机。课程内容:第一课Postgresql使用基础:发展历程、安装、建库。第二课Postgresql使用基础:客户端使用、基本对象管理。第三课Postgresql使用基础:开发应用中的基本特性。第四课Postgresql使用高级:全库备份还原。第五课Postgresql使用高级:双机环境搭建。第六课Postgresql使用高级:复制环境搭建。第七课Postgresql引擎开发基础:开发环境准备。第八课Postgresql引擎开发基础:内核逻辑结构和运行结构实现分析,跟踪调试数据库,熟悉源代码结构。 第九课Postgresql引擎开发基础:SQL语法分析器、优化器实现分析,扩展系统函数。第十课Postgresql引擎开发深入:数据迁移工具实现分析,修改完善COPY命令。第十一课Postgresql引擎开发深入:执行优化器实现分析,增加兼容其它数据库存储过程功能。第十二课Postgresql引擎开发深入:数据库数据字典实现分析,扩展系统性能动态视图。第十三课发布数据库引擎:扩展并运行数据库单元测试。第十四课发布数据库引擎:构建CentOS环境下RPM形式发布包。第十五课发布数据库引擎:大型项目迁移到自主研发数据库中,数据库层面的功能完善需求分析与设计
Navicat Premium是一个数据库开发工具,可让您从单个应用程序同时连接到MySQL,MariaDB,MongoDB,SQL Server,Oracle,PostgreSQLSQLite数据库。与Amazon RDS,Amazon Aurora,Amazon Redshift,Microsoft Azure,Oracle Cloud,Google Cloud和MongoDB Atlas等云数据库兼容。您可以快速轻松地构建,管理和维护数据库。 设置数据源连接后,可以使用“导入向导”将数据从多种格式或从ODBC传输到数据库中。将数据从表/集合,视图或查询结果导出为Excel,Access,CSV等格式。使用我们的内置编辑器添加,修改和删除记录,您可以在Tree View,JSON View和类似电子表格的经典Grid View中方便地进行编辑。Navicat为您提供有效管理数据并确保流程平稳所需的工具。 Visual SQL / Query Builder将帮助您创建,编辑和运行SQL语句/查询,而不必担心语法和命令的正确用法。通过获取关键字建议并从编码中去除重复内容,使用“代码完成”和可自定义的代码段快速进行编码。使用我们的调试组件,例如设置断点,单步执行程序,查看和修改变量值以及检查调用堆栈,可以快速找到并纠正PL / SQL和PL / PGSQL编码错误。 使用我们专业的对象设计器创建,修改和管理所有数据库对象。使用复杂的数据库设计和建模工具将数据库转换为图形表示形式,以便您可以轻松地建模,创建和理解复杂的数据库。 我们的图表功能使您可以创建大型数据集的可视表示形式,并帮助您从数据中获得更深刻的见解。探索并发掘数据之间的模式,趋势和关系,并创建有效的视觉输出,以将您的发现显示在仪表板上以进行共享。 我们功能强大的本地备份/还原解决方案以及针对MongoDump,Oracle Data Pump和SQL Server Backup Utility的直观GUI,可指导您完成备份过程并减少潜在的错误。为可重复部署的过程设置自动化,例如在特定时间或日期执行数据库备份,MapReduce作业和脚本执行。无论您身在何处,都可以随时完成工作。 使用我们的内置模式可视化工具发现和探索您的MongoDB模式。分析文档并在集合中显示丰富的结构,以便您可以了解数据的架构,查找架构异常并轻松检查异常值。 通过SSH隧道和SSL建立安全连接,可确保每个连接都是安全,稳定和可靠的。支持不同的数据库服务器身份验证方法,例如MySQL和MariaDB的PAM身份验证,MongoDB的Kerberos和X.509身份验证以及PostgreSQL的GSSAPI身份验证。Navicat提供了更多的身份验证机制和高性能环境,因此您不必担心通过不安全的网络进行连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值