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)

时间: 2024-10-14 15:58:48

PostgreSQL 常见慢SQL问题解决方法的相关文章

mysql 的常用命令及常见问题解决方法

运行sql C:\Users\Martin>mysql -uroot -pyang cdm_db <d:/cdm_db.sql 运行sql mysql>source /tmp/terminal.sql; mysql忘记密码: mysqladmin -uroot flush-privileges password "newpassword" mysql的select into file命令 SELECT a,b,a+b INTO OUTFILE '/tmp/result

附:02 eclipse常见问题解决方法

一.出现"Location of the Android SDK has not been setup in the preferences" 当新建一个工作区间时,android项目时出现"Location of the Android SDK has not been setup in the preferences"时,是因为没有设置SDK的位置,window->preferences->android->SDK Location里面选择你的

SQL Server &#39;已超过了锁请求超时时段&#39; 问题解决方法

SQL 有时遇到 已超过了锁请求超时时段. (Microsoft SQL Server,错误: 1222) 这个错误,刷新以后,右击某张表或者库,发现里面的表全部消失了 或者查询不到. 这是因为 sql进程死锁,资源被抢占,要解决这个问题,得杀死关闭 死锁的进程,下面介绍解决方案: 杀死进程的前提是找到 那个死锁的进程 , SELECT blocking_session_id '阻塞进程的ID', wait_duration_ms '等待时间(毫秒)', session_id '(会话ID)'

Web Deploy发布网站及常见问题解决方法(图文)

Web Deploy发布网站及常见问题解决方法(图文) Windows2008R2+IIs7.5 +Web Deploy 3.5 Web Deploy 3.5下载安装 http://www.iis.net/downloads/microsoft/web-deploy 点 Install this extension 也可直接点下面链接 http://go.microsoft.com/?linkid=9817356 全部 点下一步进行安装 直至完成, Web Deploy 安装完毕后,便可进行下一

CString的GetBuffer用法,GetBuffer本质,GetBuffer常见问题解决方法

一.函数原型 CString::GetBuffer LPTSTR GetBuffer( int nMinBufLength ); throw( CMemoryException ); Return Value An LPTSTR pointer to the object’s (null-terminated) character buffer. Parameters nMinBufLength The minimum size of the character buffer in charac

QTP录制不了脚本常见问题解决方法

问题起因:  在安装QTP后,或者禁用IE浏览器里的一些ActiveX控件后,正常录制QTP时,不能产生相应的录制脚本,脚本内容为空.  解决方法:QTP在IE中录制脚本是依靠一个叫BHOManager Class的动态链接库来完成的.当这个控件没有被加载,或者被禁用时,就会出现上述症状.于是,解决方法就很简单了,重新加载,或启用这个控件,一切就OK啦. 具体步骤:  打开IE,在菜单中选择[工具]/[Internet选项]进入Internet配置界面.选择[程序]/[管理加载项],查看目前加载

网易视频云技术分析:IOS工程常见问题解决方法

网易视频云是网易推出的视频云服务,目前已经y广泛应用于在线教育.秀场直播.远程医疗.企业协作等领域.现在,网易视频云的技术专家们给大家分享一则移动APP测试技术文:IOS工程常见问题解决方法. 最近在做IOS测试时,碰到了几个环境引起的问题,主要是开发工具新版本及IOS系统新版本特性导致.现挑取两个比较典型的问题来分享给大家. 1. Xcode版本引出的问题 问题描述:开发提测时,创建的工程是在xcode6版本上创建的,而测试环境使用新的版本Xcode7,将开发提测工程导入后进行编译报如下错误:

嵌入式开发常见问题解决方法

嵌入式开发常见问题解决方法 一.问题复现 稳定复现问题才能正确的对问题进行定位.解决以及验证.一般来说,越容易复现的问题越容易解决. 1.1 模拟复现条件 有的问题存在于特定的条件下,只需要模拟出现问题的条件即可复现.对于依赖外部输入的条件,如果条件比较复杂难以模拟可以考虑程序里预设直接进入对应状态. 1.2 提高相关任务执行频率 例如某个任务长时间运行才出现异常则可以提高该任务的执行频率. 1.3 增大测试样本量 程序长时间运行后出现异常,问题难以复现,可以搭建测试环境多套设备同时进行测试.

苹果CMSv10常见使用问题解决方法

原文摘自:https://www.mytheme.cn/article/116.html 下面汇集的是苹果CMSv10在使用中常见问题解决方法.请根据自己遇到的问题找到正确的答案来排忧解难. 1,上传文件失败常见问题?由于采用最新的TP框架,需要开启php的fileinfo支持库,在php.ini里 extension=php_fileinfo.dll :宝塔等面板里直接安装fileinfo插件即可 .上传文件失败问题请检查php临时文件目录权限和cms系统文件存储目录权限.windows系统一