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语句调优相关方法的更多相关文章

  1. SQL语句调优-基础知识准备

    当确定了应用性能问题可以归结到某一个,或者几个耗时资源的语句后,对这些语句进行调优,就是数据库管理员或者数据库应用程序开发者当仁不让的职责了.语句调优是和数据库打交道的必备基本功之一. 当你面对一个“ ...

  2. MySQL千万级多表关联SQL语句调优

    本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化.   需要优化的查询:使用explain      出现了Using temporary:       ...

  3. MySQL百万级、千万级数据多表关联SQL语句调优

    本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使百万级.千万级数据表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果).希望读者能够理解S ...

  4. SQL语句调优三板斧

    改装有顺序------常开的爱车下手 你的系统中有成千上万的语句,那么优化语句从何入手呢 ? 当然是系统中运行最频繁,最核心的语句了.废话不多说,上例子: 这是一天的语句执行情况,里面柱状图表示的是对 ...

  5. SQL语句调优汇总

    1.插入数据的表或临时表,预先创建好表结构,能够加快执行速度 2.where 条件判断的字段以及连接查询的条件字段   都添加上索引   能够加快执行速度 3.尽量避免使用 like ,类似 like ...

  6. 【初学Java学习笔记】SQL语句调优

    1, 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2,应尽量避免在 where 子句中对字段进行 null 值判断,创建表时NULL是默认 ...

  7. SQL语句调优 - 统计信息的含义与作用及维护计算

    统计信息的含义与作用                                                                                          ...

  8. SQL语句调优 - 索引上的数据检索方法

    如果一张表上没有聚集索引,数据将会随机的顺序存放在表里.以dbo.SalesOrderDetail_TEST为例子.它的上面没有聚集索引,只有一个在SalesOrderID上的非聚集索引.所以表格的每 ...

  9. SQL 语句调优 where 条件 数据类型 临时表 索引

    基本原则 避免全表扫描 建立索引 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理 尽量避免大事务操作,提高系统并发能力 使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方 ...

随机推荐

  1. ifame子页实现父页面刷新(或跳转到指定页面)

    <script>parent.location.replace('../D_DailyManager/Add.aspx?id=" + x + "');</scri ...

  2. E5中遍历数组的方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 初学C#,总结一下.sln和.csproj的区别

    1.sln:solusion 解决方案 csproj:c sharp project C#项目 csproj文件大家应该不会陌生,那就是C#项目文件的扩展名,它是“C Sharp Project”的缩 ...

  4. PHP关于注册注意的问题

    1.注意转义字符的问题 get_magic_quotes_gpc()开启时,所有的 ' (单引号), " (双引号), \(反斜线) and 空字符(null)会自动转为含有反斜线的溢出字符 ...

  5. 关于C++程序运行程序是出现的this application has requested the runtime to terminate it in an unusual way. 异常分析

    今天运行程序是出现了this application has requested the runtime  to terminate it in an unusual way. 的异常报告,以前也经常 ...

  6. CorelDRAW升级计划--如何购买

    了解通过全新 CorelDRAW 2017升级计划更新此图形设计软件所有最新功能的实惠方案.助升级计划,您可以在下一主要产品版本推出时便收到该版本,从而始终使您的产品保持最新.升级计划取代为 X6 和 ...

  7. C语言基本语法——函数

    1.什么是函数 2.函数语法 3.函数声明 4.函数调用 5.函数的形参与实参 6.return与exit关键字 7.递归函数 1.什么是函数 • 函数就是一连串语句被组合在一起,并指定了一个名字 • ...

  8. 【BZOJ5020】[LOJ2289]【THUWC2017】在美妙的数学王国中畅游 - LCT+泰勒展开

    咕咕咕?咕咕咕! 题意: Description 数字和数学规律主宰着这个世界. 机器的运转, 生命的消长, 宇宙的进程, 这些神秘而又美妙的过程无不可以用数学的语言展现出来. 这印证了一句古老的名言 ...

  9. web自动化-selenium2入门讲解(mac版本)

    最近要做一个selenium2的分享,于是总结了下我用selenium2的感受,希望分享出来,可以对入门的小伙伴有一点帮助,也希望得到大佬的指教   一,环境搭建maven+selenium2+tes ...

  10. [读书笔记] R语言实战 (十四) 主成分和因子分析

    主成分分析和探索性因子分析是用来探索和简化多变量复杂关系的常用方法,能解决信息过度复杂的多变量数据问题. 主成分分析PCA:一种数据降维技巧,将大量相关变量转化为一组很少的不相关变量,这些无关变量称为 ...