PostgreSQL 常见慢SQL问题解决方法


刚熟悉PG的开发者接触PG时,或多或少会碰到一些问题.
常见的表现是碰到一些慢SQL.这时候别急着吐槽.绝大多数并不是问题,稍微的语法调整或进行一些简单的优化就能解决问题.下面具体分析几个案例.

一: 中文字符串的索引扫描慢
test =# \d testidx
                  Table"test.testidx"    
Column         |        Type                 | Modifiers
----------------+-----------------------------+-----------
id             | numeric                     |  
table_id       | numeric                     |
description    | character varying(4000)     |
user_comment   | character varying(4000)     |
encoding       | character varying(64)       |

这是一个很常见的表,它所在database的 Encoding Collate Ctype 都是zh_CN.UTF-8
为了检索description的信息,很常见的(www.neitui.me),我们在该列上创建一个btree索引.
test=# create index  idx_testidx on testidx(description);                    
CREATE INDEX

检索列中的信息使用like语句进行匹配,发现查询计划居然没有使用索引.


test=# explain select description from testidxwhere description like 'test%';          
                         QUERY PLAN                          
-------------------------------------------------------------
SeqScan on testidx  (cost=0.00..30151.00rows=64 width=28)
  Filter: ((description)::text ~~ 'test%'::text)
(2 rows)

有点不甘心,禁掉索引看个究竟,索引是用上了,但是条件过滤放到了索引外.数据用索引扫描获取,生成了位图,然后走Bitmap Heap Scan,很明显这是有问题的.


test=# set enable_seqscan=off;
SET
test=# explain select description from testidxwhere description like 'test%';
                                     QUERYPLAN                                    
------------------------------------------------------------------------------------
Bitmap Heap Scan on testidx  (cost=29756.57..59907.57 rows=64 width=28)
  Filter: ((description)::text ~~ 'test%'::text)
  ->  Bitmap Index Scan on idx_testidx  (cost=0.00..29756.55 rows=1000000 width=0)
(3 rows)


实际的执行一遍,看看执行情况,也不乐观,1000000行数据都取了出来,堆扫描的过滤器过滤掉所有的行
执行该SQL用了接近半秒,太慢了.


test=# explain analyze select description fromtestidx where description like 'test%';
                                                               QUERY PLAN                                                              
----------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on testidx  (cost=29756.57..59907.57 rows=64 width=28)(actual time=407.548..407.548 rows=0 loops=1)
  Filter: ((description)::text ~~ 'test%'::text)
  Rows Removed by Filter: 1000000
  ->  Bitmap Index Scan onidx_testidx  (cost=0.00..29756.55rows=1000000 width=0) (actual time=166.581..166.581 rows=1000000 loops=1)
Total runtime: 407.590 ms
(5 rows)

原因很简单
1 在utf8编码下表中的列需要按照utf8的规则来操作(各种操作符 > =< (~~)like 等)
2 创建索引时没有指定比较方式,默认采用standard"C"的字符串比较方法在UTF8上只支持 = 操作符.
3 创建索引时指定特定的比较方式能支持索引的like.
4 btree gin hash索引的用法相同.
5 pg中char varchar text数据类型适用上述规则.

The operator classes text_pattern_ops,varchar_pattern_ops, and bpchar_pattern_ops support B-tree indexes on the typestext, varchar, and char respectively. The difference from the default operatorclasses is that the values are compared strictly character by character ratherthan according to the locale-specific collation rules. This makes theseoperator classes suitable for use by queries involving pattern matchingexpressions (LIKE or POSIX regular expressions) when the database does not usethe standard "C" locale. As an example, you might index a varcharcolumn like this:

来看看create index的语法:

CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [name ] ON table_name [ USING method ]
    ({ column_name | ( expression ) } [  ] [opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
    [WITH ( storage_parameter = value [, ... ] ) ]
    [TABLESPACE tablespace_name ]
    [WHERE predicate ]
collation
The name of the collation to use for theindex. By default, the index uses the collation declared for the column to beindexed or the result collation of the expression to be indexed. Indexes withnon-default collations can be useful for queries that involve expressions usingnon-default collations.

于是,可以用该语法创建对应可用的索引.
test=# create index  idx_testidx2 on testidx(description varchar_pattern_ops);
CREATE INDEX

让我们来看看效果,Index Cond出现了.使用索引扫描,并且做了条件过滤,可能有64行有效数据.
test=# explain select description from testidxwhere description like 'test%';  

                                     QUERYPLAN                                    
------------------------------------------------------------------------------------
Index Only Scan using idx_testidx2 ontestidx  (cost=0.55..8.57 rows=64width=28)
  Index Cond: ((description ~>=~ 'test'::text) AND (description ~<~'tesu'::text))
  Filter: ((description)::text ~~ 'test%'::text)
(3 rows)


实际执行结果验证了索引的有效性,SQL效率执行效果明显.


test=# explain analyze select description fromtestidx where description like 'test%';
                                                        QUERY PLAN                                                        
-----------------------------------------------------------------------------------------------------------------------------
Index Only Scan using idx_testidx2 ontestidx  (cost=0.55..8.57 rows=64width=28) (actual time=0.081..0.081 rows=0 loops=1)
  Index Cond: ((description ~>=~ 'test'::text) AND (description ~<~'tesu'::text))
  Filter: ((description)::text ~~ 'test%'::text)
  Heap Fetches: 0
Total runtime: 0.105 ms
(5 rows)

转载于:https://www.cnblogs.com/xiaohuinihao/p/5007581.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在优化PostgreSQLSQL时,有几个关键的步骤和参数可以帮助我们进行调优。 首先,需要关注SQL的跟踪和分析。可以通过启动日志收集功能来追踪SQL。在以RPM方式安装的数据库中,默认情况下,日志收集功能是打开的。而在以源码编译的方式安装的数据库中,默认是关闭的。通过启用日志收集,系统将记录执行时间超过某个阈值的SQL语句。这个阈值可以通过设置参数来指定,默认单位是毫秒。 其次,需要对SQL进行分析和优化。可以使用不同的工具和技术来识别和解决SQL问题。其中一种常用的方法是通过Explain语句来查看SQL语句的执行计划,以确定是否存在性能瓶颈。还可以通过执行计划中的成本估计来确定哪些操作消耗了最多的资源,从而进行针对性的优化。 另外,对于SQL语句本身的优化也是很重要的。可以考虑使用索引来加速查询,避免不必要的全表扫描。还可以通过重构或优化SQL语句的逻辑,减少不必要的计算和IO操作,并合理使用数据库的特性和功能。 总之,通过启用日志收集功能,分析执行计划和优化SQL语句,可以帮助我们进行PostgreSQLSQL调优,提升数据库的性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [PostgreSQL SQL 语句](https://blog.csdn.net/weixin_45694422/article/details/121231478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值