SQL语句调优相关方法
SQL语句慢的原因:
1,数据库表的统计信息不完整
2,like查询估计不准确
调优方法:
1,查看表中数据的条数;
2, explain analyze target_SQL;
查看SQL执行计划;
比较SQL总执行时间和各个部分actual time的大小
可以更改SQL的执行顺序
可以执行部分SQL语句逐步分析慢的地方;
有问题的SQL,row估计有问题。
函数调整为比较常量
postgresql join_colapse
1 PostgreSQL SQL的性能调试方法--借助统计信息
在数据库应用开发中,速度慢的SQL比比皆是。很多速度很慢都是SQL写的不好,效率不高。比如无用的循环查询,判断,
不必要的子查询,写的SQL用不上索引等等。特别是数据量很大的时候,很是头疼。
几千万条数据的表的查询,由于子查询过多,要几个小时才执行完。显然是不符合要求的。
要解决这个速度问题 ,我们首先最主要的是要找到那些SQL很慢,或者SQL中的那部分很慢。怎样寻找速度很慢的SQL,我 们 可以借助系 统 提供的 统计 信息功能来 查 找。
1.pg_stat_user_functions :SQL文中用了存储过 程或者函数的情况,可以通 过这 个 统计 信息view来查看。
funcid, schemaname, funcname :函数的ID
calls : 执行次数
total_time : 函数执行的总时间,单位毫秒。
self_time : 不包含其他函数的执 行 时间 的自己本身的 执 行 时间 。
例子:
=# SELECT * FROM pg_stat_user_functions;
funcid | schemaname | funcname | calls | total_time | self_time
--------+------------+----------+-------+------------+-----------
16434 | public | proc_1 | 4 | 185 | 185
16738 | public | proc_2 | 5 | 91 | 91
16741 | public | proc_3 | 2 | 76 | 5
(3 rows)
从这里面我们可以看到proc_3自己自身执行的时间相对于总的时间来说耗费的时间非常少,
可以初步确定速度慢的函数不是proc_3。因此我就需要去查询其他函数的执行时间。
这个机能系统默认是没有的,需要在postgresql.conf 里面设置。默认是none。需要改为pl或者all。
track_functions = pl # none, pl, all
2.pg_stat_statements :contrib/pg_stat_statements模块下的机制,系统默认也是没有的。
userid : 执行SQL的用户
dbid : 数据库 ID
query : SQL文
calls : 执行次数
total_time : 执行总时间,单位微秒。
rows : 处理行数。返回的行数或者修改的行数。
例子:
SELECT query, calls, total_time, rows
FROM pg_stat_statements ORDER BY total_time DESC LIMIT 3;
-[ RECORD 1 ]------------------------------------------------------------
query | UPDATE branches SET bbalance = bbalance + $1 WHERE bid = $2;
calls | 3000
total_time | 35.9654100
rows | 3000
这个功能也是需要在postgresql.conf 里面设置。
shared_preload_libraries = 'pg_stat_statements'
custom_variable_classes = 'pg_stat_statements'
通过上面的两种方法我们就可以找到那些SQL或者函数很慢,这样就能够对症下药了,
要不然真是找不原因,很耗费时间。
2 PostgreSQL SQL的性能调试方法--数据库log分析
1.log_min_duration_statement
从log找出执行超过一定时间的 SQL。postgresql.conf配置文件设置 log_min_duration_statement参数的值。
这个参数是设置执行最小多长时间的SQL输出到log。
例如输出执行超过 3秒的SQL:log_min_duration_statement = 3s
这个参数设置为 -1是无效。 设置为 0是输出所有的SQL,但这样会增加服务器负担,一般不要设置太低的值。
这样设置后输出的SQL例子如下:
LOG: duration: 3016.724 ms statement: SELECT count(*)
FROM pg_class
2.contrib/auto_explain功能。Postgres8.4后增加的功能。
默认这个功能不能使用的,需要在postgresql.conf 配置文件中设置以下参数。
shared_preload_libraries = 'auto_explain'
custom_variable_classes = 'auto_explain'
auto_explain.log_min_duration = 4s
这样系统在执行的时候如果遇到超过4秒的SQL的话,会自动把执行计划输出到log。这样就直接看log就更加容易找到问题点。
执行计划例子:
LOG: duration: 4016.724 ms plan:
Aggregate (cost=14.90..14.91 rows=1 width=0)
-> Hash Join (cost=3.91..14.70 rows=81 width=0)
Hash Cond: (pg_class.oid = pg_index.indrelid)
-> Seq Scan on pg_class (cost=0.00..8.27 rows=227 width=4)
-> Hash (cost=2.90..2.90 rows=81 width=4)
-> Seq Scan on pg_index (cost=0.00..2.90 rows=81 width=4)
Filter: indisunique
STATEMENT: SELECT count(*)
FROM pg_class, pg_index
WHERE oid = indrelid AND indisunique;
3.log统计分析工具(PostgreSQL log analyzer)
比较有名是pgFouine 。这个工具是自动分析指定的log,然后生成HTML报表。把SQL log图像化后更加直观。
可以统计分析最慢的SQL,调用最多的SQL,花费时间最多的SQL等等分类。这样我们就很容易找到速度慢的SQL。再加以改善。
3 PostgreSQL SQL的性能调试方法--查看执行计划
利用pgAdmin中的自带的 查看 执行计划工具。 我 们 用的最多的就是 这 个工具, 这 个工具因 为 不需要其他什么配置或安装。
这个工具也是PostgreSQL主打的调试工具。
1.下面简单介绍一下执行计划结果的读法
①Explaining → Widths
=# EXPLAIN SELECT oid FROM pg_proc;
QUERY PLAN
------------------------------------------
Seq Scan on pg_proc
(cost=0.00..87.47 rows=1747 width=4)
查询结果的所有字段的总宽度。这个参数并不是关键指标。每个字段的宽度定义如下:
text [ n 文字]:n+4
varchar(n):n+1
char(n):n+1
boolean:1
bigint :8
integer:4
②Explaining → Rows
预测的行数。与实际的行数可能有出入,经常vacuum或者analyze的话,这个值和实际值将更加接近。
③Explaining → Cost
cost是比较重要的指标。例子中的cost=0.00..87.47有两个部分,启动时间(startup)=0.00 和总时间(total)=87.47。单位是毫秒。这个指标也只是预测值。
启动时间也有解释为找到符合条件的第一行所花的时间。
④Explaining → Explain Analyze
想知道实际的执行时候的执行计划的话,用这个命令。
=# EXPLAIN ANALYZE SELECT oid FROM pg_proc;
QUERY PLAN
------------------------------------------
Seq Scan on pg_proc
(cost=0.00..87.47 rows=1747 width=4)
(actual time=0.077..17.082 rows=1747 loops=1)
Total runtime: 20.125 ms
loops:循环的次数。
Total runtime:总的时间
⑤Explaining → 执行计划运算类型
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。有启动时间。
下面是一个hash,hash join例子:
=# EXPLAIN SELECT relname, nspname FROM pg_class JOIN
pg_namespace ON (pg_class.relnamespace=pg_namespace.oid);
QUERY PLAN
------------------------------------------------------------------------
Hash Join (cost=1.06..10.71 rows=186 width=128)
Hash Cond: ("outer".relnamespace = "inner".oid)
-> Seq Scan on pg_class (cost=0.00..6.86 rows=186 width=68)
-> Hash (cost=1.05..1.05 rows=5 width=68)
-> Seq Scan on pg_namespace (cost=0.00..1.05 rows=5 width=68)
两个表间 INNER JOIN和LEFT OUTER JOIN 连接的时候,这个运算是很常用的。 这个运算是先把外表中关联条件部分做一个哈希表,然后去和内部表关联。
下面是一个Nested Loop例子:
=# SELECT * FROM pg_foo JOIN pg_namespace
ON (pg_foo.pronamespace=pg_namespace.oid);
QUERY PLAN
----------------------------------------------------------------------
Nested Loop (cost=1.05..39920.17 rows=5867 width=68)
Join Filter: ("outer".pronamespace = "inner".oid)
-> Seq Scan on pg_foo (cost=0.00..13520.54 rows=234654 width=68)
-> Materialize (cost=1.05..1.10 rows=5 width=4)
-> Seq Scan on pg_namespace (cost=0.00..1.05 rows=5 width=4)
两个表间 INNER JOIN和LEFT OUTER JOIN 连接的时候,这个运算是很常用的。这个运算是扫描外表,然后去内部找所符合条件的记录。
哈希运算要做一张哈希表,如果外部的tb1的数据不是特别多的时候是比较快的。如果tb1相当大,这时候做一张可能花时候反而更多。
因为做的哈希表内存装不下,需要输出到硬盘,这样IO读取多了,速度就低下了。
合并查询对外部和内部表都要用两个表的关联字段各自做一张,并且还要排序。
如果是已经拍好序的,速度是很快。这中运算有数据特大的时候
还有可能不如循环结合快。
因此我们有个别地方可能直接用系统默认的执行计划的话反而很慢。如果是那样的话,可以尝试强制改变执行计划。禁止使用hash结合或合并结合。
这个要具体问题具体分析。
2. 强制改 变执行计划
有时候我们不想用系统默认的执行计划。这时候就需要自己 强制控制 执行计划。
禁止某种运算的SQL语法: SET enable_运算 类型 = off; //或者=false
开启某种运算的SQL语 法:SET enable_运算 = on; //或者=true
执行计划可以改 变 的运算方法如下:
– enable_bitmapscan
– enable_hashagg
– enable_hashjoin
– enable_indexscan
– enable_mergejoin
– enable_nestloop
– enable_seqscan
– enable_sort
– enable_tidscan
如果我们只想改变当前要执行的SQL的执行计划,而不想影响其他的SQL的话。在设置SQL里面加一个关键字session即可。
例子: set session enable_hashjoin=false //禁止使用哈希结合算法
通过查看执行计划,我们就能够找到SQL中的哪部分比较慢,或者说花费时间多。然后重点分析哪部分的逻辑,
比如减少循环查询,或者强制改变执行计划。
SQL语句调优相关方法的更多相关文章
- SQL语句调优-基础知识准备
当确定了应用性能问题可以归结到某一个,或者几个耗时资源的语句后,对这些语句进行调优,就是数据库管理员或者数据库应用程序开发者当仁不让的职责了.语句调优是和数据库打交道的必备基本功之一. 当你面对一个“ ...
- MySQL千万级多表关联SQL语句调优
本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化. 需要优化的查询:使用explain 出现了Using temporary: ...
- MySQL百万级、千万级数据多表关联SQL语句调优
本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使百万级.千万级数据表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果).希望读者能够理解S ...
- SQL语句调优三板斧
改装有顺序------常开的爱车下手 你的系统中有成千上万的语句,那么优化语句从何入手呢 ? 当然是系统中运行最频繁,最核心的语句了.废话不多说,上例子: 这是一天的语句执行情况,里面柱状图表示的是对 ...
- SQL语句调优汇总
1.插入数据的表或临时表,预先创建好表结构,能够加快执行速度 2.where 条件判断的字段以及连接查询的条件字段 都添加上索引 能够加快执行速度 3.尽量避免使用 like ,类似 like ...
- 【初学Java学习笔记】SQL语句调优
1, 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2,应尽量避免在 where 子句中对字段进行 null 值判断,创建表时NULL是默认 ...
- SQL语句调优 - 统计信息的含义与作用及维护计算
统计信息的含义与作用 ...
- SQL语句调优 - 索引上的数据检索方法
如果一张表上没有聚集索引,数据将会随机的顺序存放在表里.以dbo.SalesOrderDetail_TEST为例子.它的上面没有聚集索引,只有一个在SalesOrderID上的非聚集索引.所以表格的每 ...
- SQL 语句调优 where 条件 数据类型 临时表 索引
基本原则 避免全表扫描 建立索引 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理 尽量避免大事务操作,提高系统并发能力 使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方 ...
随机推荐
- div position:fixed后,水平居中的问题
.div{position:fixed;margin:auto;left:0; right:0; top:0; bottom:0;width:200px; height:150px;}
- 高德SDK获取到的坐标转换为GPS真实坐标方法,Java版
发现高德SDK不提供高德的坐标转GPS坐标(GCJ_02转WGS_84),下面是一份Java版的 /**************************** 文件名:GCJ2WGS.java 创建时间 ...
- 五年磨一剑:Java 开源博客 Solo 1.0.0 发布了!
从 Solo 第一个版本发布至今,已经过去 5 年了.今天我们非常自豪地宣布,Solo 1.0.0 正式发布,感谢一直以来关注 B3log 开源的朋友! 目前 B3log 开源有三款产品: GitHu ...
- C++ 简单内存泄漏检测方法
遇到个bug,MFC程序异常退出,debug模式下输出 Detected memory leaks! Dumping objects -> {366566} normal block at 0x ...
- JOptionPane提示框的一些常用用法
1.1 showMessageDialog 显示一个带有OK 按钮的模态对话框. 下面是几个使用showMessageDialog 的例子: JOptionPane.showMessageDialog ...
- ZBrush与同类数字雕刻软件的比较
随着数字雕刻软件的迅猛发展,不但在软件的数量和功能上有突飞猛进的提高,行业应用上也有很大的拓展.那么,与同类数字雕刻软件比较下,用户应该如何选择呢?下面我们来对这些软件做一个简单的罗列分析. 目前数字 ...
- [置顶]
献给写作者的 Markdown 新手指南
作者:http://jianshu.io/p/q81RER 出处:http://jianshu.io/p/q81RER 献给写作者的 Markdown 新手指南 简书 「简书」作为一款「写作软件」在诞 ...
- 使用ajax实现搜索功能
最近要做一个搜索功能,网上搜了一圈,终于做出来了,很简单的一个,这里分享我的方法,希望对大家有用,不足之处还请指教. 这里使用ajax提交数据,配合jquery将数据显示出来. 用jq的keyup ...
- bzoj 1814 Fornula 1
Formula 1 题意 在\(n*m\)的矩阵中,有些格子有树,没有树的格子不能到达,找一条回路,吃完所有的树,求有多少种方法. 解法 因为只要一条回路,所以我们必须维护插头的连通性. 具体的可以参 ...
- myeclipse的git插件安装
首先需要一个myeclies的Git插件EGit 点击下载5.0.1 官方网站