【数据库学习】PostgreSQL优化

  1. pg安装与运维
  2. Postgres原理及底层实现
  3. 基础语法
  4. SQL优化
  5. 中文文档

1,数据库减负思路

  1. 缓存 + 页面静态化
    实时性不高的数据;
  2. 数据库优化=sql优化 + 表结构优化 + 数据库分区分表
    合并数据库操作,将多次操作合并成一条sql执行。
  3. 热点数据分离
    主表只保存活跃数据。
  4. 数据库读写分离

2,执行计划

1)场景

explain只能分析:SELECT、INSERT、DELETE、UPDATE和DECLARE…CURSOR命令。

2)使用

ANALYZE 缺省表示只计划;加上表示查看实际执行成本。

#查看执行计划。也可以使用navicat的解释功能查看。
explain [ANALYZE] sql语句;  

3)结果说明

1>算子

2>缓存-shared

  • Hit - 命中
  • Read - 读磁盘
  • Dirtied - 脏页(脏页包含在Hit中)

3>统计数据

QUERY PLAN
Index Scan using tenk1_unique1 on tenk1  (cost=0.00..10.01 rows=1 width=244)
  1. cost:启动开销…总开销。
    不过事实总开销可能会低一点:带有 LIMIT 子句的查询将会在 Limit 规划节点的输入节点里很快停止。
  2. rows:预计输出的行数
   Index Cond: (unique1 < 3)  --从索引中检索出的行的过滤器
   Filter: (stringu1 = 'xxx'::name)
  1. Filter:过滤条件
QUERY PLAN
--嵌套循环
 Nested Loop  (cost=2.37..553.11 rows=106 width=488) 
   ->  Bitmap Heap Scan on tenk1 t1  (cost=2.37..232.35 rows=106 width=244) 
         Recheck Cond: (unique1 < 100)
         --位图索引
         ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..2.37 rows=106 width=0)
               Index Cond: (unique1 < 100)
   ->  Index Scan using tenk2_unique2 on tenk2 t2  (cost=0.00..3.01 rows=1 width=244)
         Index Cond: ("outer".unique2 = t2.unique2)


QUERY PLAN
--内存 Hash 表
 Hash Join  (cost=232.61..741.67 rows=106 width=488)
   Hash Cond: ("outer".unique2 = "inner".unique2)
   ->  Seq Scan on tenk2 t2  (cost=0.00..458.00 rows=10000 width=244)
   ->  Hash  (cost=232.35..232.35 rows=106 width=244)
         ->  Bitmap Heap Scan on tenk1 t1  (cost=2.37..232.35 rows=106 width=244)
               Recheck Cond: (unique1 < 100)
               ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..2.37 rows=106 width=0)
                     Index Cond: (unique1 < 100)

3,SQL优化

对于重复的代码逻辑,sql执行速度远远大于代码逻辑。
但是,由于sql难以测试、难以复用、难以加工变量,对于复杂的逻辑不建议用在sql中。代码可以分成模块、逻辑独立、方便测试。

sql优化的思路有两种:
一是:

The fastest way to do something is don’t do it
去掉无用的步骤

二是优化算法,如让sql走更优的执行计划上。

1)概念

1>引擎优化策略

基于规则的优化(RBO,Rule Based Optimizer)
这是一种比较老的技术,简单说基于规则的优化就是当数据库执行一条query语句的时候必须遵循预先定义好的一系列规则(比如oracle的15条规则,排名越靠前的执行引擎认为效率越高)来确定执行过程,它不关心访问表的数据分布情况,仅仅凭借规则经验来确定,所以说是一种比较粗放的优化策略。

基于代价的优化(CBO,Cost Based Optimizer)
基于代价的优化的产生就是为了解决上面RBO的弊端,让执行引擎依据预先存储到数据库中表的一些实时更新的统计信息来选择出最优代价最小的执行计划来执行query语句,CBO会根据统计信息来生成一组可能被使用到的执行计划,进而估算出每个计划的代价,从而选择出代价最小的交给执行器去执行,其中表的统计信息一般会有表大小,行数,单行长度,单列数据分布情况,索引情况等等。

总结:
基于规则的优化器更像是一个经验丰富熟知各条路段的老司机,大部分情况可以根据自己的经验来判断走哪条路可以更快的到达目的地,而基于代价的优化更像手机里面的地图,它可以选择出许多不同的路径根据实时的路况信息综合考虑路程长度,交通状况来挑出最优的路径。

2)SQL高性能归约

1>查询

  1. 禁止使用select * ,用SELECT <字段列表> 查询;
  2. 同一列操作,用in代替or。
    in 操作可以更有效的利用索引,or 大多数情况下很少能利用到索引。

2>表连结

  1. 联结的表越多效率越低,一般<5张;
    SQL本身不限制联结表的数目,但DBMS有最大数目限制。
  2. join查询一般比子查询快;
  3. 小表驱动大表+ 合适索引(给大表的join条件建立索引)+ 合理运用连接条件(大表改成二次查询表,通过where语句过滤大部分数据),基本上连接可以解决绝大部分问题。
  4. 排序字段必须是驱动表字段,不然可能用不到索引。

3>数据库层面

  1. 减少同数据库的交互次数,合并多个相同操作。

4>表设计

  1. 表数据量的大小<500w
  2. 分区表
    分区表由多个文件存储,逻辑上表现为一个表。
    跨区查询效率更低。
  3. 尽量做到冷热数据分离,减少表的宽度。
  4. 禁止在表中建立预留字段
    预留字段的命名很难做到见名识义 预留字段无法确认存储的数据类型,所以无法选择合适的类型 对预留字段类型的修改,会对表进行锁定。
  5. 禁止在数据库中存储图片,文件等大的二进制数据;
  6. 优先选择符合存储需要的最小的数据类型。
    列的字段越大,建立索引时所需要的空间也就越大。
  7. 必须有主键、update_time;

4,配置优化

pg中与内存有关的配置参数:

1>shared_buffers(共享缓存区)

i>工作原理

shared_buffers是一个8KB的数组,postgres在从磁盘中查询数据前,会先查找shared_buffers的页,如果命中,就直接返回,避免从磁盘查询。
多个进程通过共享内存技术来共享缓存中的数据。

  1. shared_buffers存储什么?
    表数据;
    索引,索引也存储在8K块中;
    执行计划,存储基于会话的执行计划,会话结束,缓存的计划也就被丢弃。

  2. 什么时候加载shared_buffers?
    1)在访问数据时,数据会先加载到os缓存,然后再加载到shared_buffers,这个加载过程可能是一些查询,也可以使用pg_prewarm预热缓存。
    2)当然也可能同时存在os和shared_buffers两份一样的缓存(双缓存)。
    3)查找到的时候会先在shared_buffers查找是否有缓存,如果没有再到os缓存查找,最后再从磁盘获取。
    4)os缓存使用简单的LRU(移除最近最久未使用的缓存),而数据库采用的优化的时钟扫描,即缓存使用频率高的会被保存,低的被移除。

ii>优化策略

提高shared_buffers,增加缓存命中率,提高查询效率。
同时为了避免Double Buffering问题,将shared_buffers设置较小,更多的内存留给文件系统使用。

  1. 【Double Buffering(双缓存)】问题:
    pg的数据文件都存储在文件系统中,os的文件系统也有缓存,这导致pg的数据库副本可能同时存在于共享内存和文件系统中,造成内存利用率低的问题。
    Oracle中通过设置Birect I/O避免双缓存问题,但pg不支持。 shared_buffers的大小不应该超过内存的1/4。

  2. shared_buffers设置的合理范围
    1)windows服务器有用范围是64MB到512MB,默认128MB
    2)linux服务器建议设置为25%,亚马逊服务器设置为75%(避免双缓存,数据会存储在os和shared_buffers两份)
    os缓存的重要性:数据写入时,从内存到磁盘,这个页面就会被标记为脏页,一旦被标记为脏页,它就会被刷新到os缓存,然后写入磁盘。所以如果os高速缓存大小较小,则它不能重新排序写入并优化io,这对于繁重的写入来说非常致命,因此os的缓存大小也非常重要。给予shared_buffers太大或太小都会损害性能。

  3. shared_buffers调整策略

2> work_mem

为每个进程单独分配的内存,主要用于group by, sort, hash agg, hash join 等操作。
注意:work_mem是每次分配的内存,加入有M个并发进程,每个进程有N个HASH操作,那么需要分配的内存为 MNwork_mem。因此work_mem不宜设置太大,通常保持默认的4MB即可,如果设置的太大超过256MB,很容易因为瞬间的大并发操作导致oom。

3>maintenance_work_mem

为每个进程单独分配的内存,主要进行维护操作时需要的内存,如VACUUM、create index、ALTER TABLE ADD FOREIGN KEY等操作需要的内存。

4>autovacuum_work_mem

pg9.4版本新增参数。
9.4之后,AutoVacuum的worker进程分配的内存由参数autovacuum_work_mem控制,手动Vacuum时分配的内存由maintenance_work_mem 控制。9.4之前都用maintenance_work_mem 参数。
默认值为-1,表示与maintenance_work_mem 一样。
vacuum 大小 = autovacuum_max_workers * autovacuum_work_mem

5>temp_buffers(临时表缓存)

为每个不同的进程单独分配的内存,不在共享内存中,默认为8MB。

6>wal_buffers(WAL日志缓存大小)

默认为-1,表示根据shared_buffer的大小自动设置。

7>huge_pages(是否使用大页)

默认值为try,表示尽量使用大页。若os未开启大页,不使用大页内存,不影响数据库正常使用。

8>effective_cache_size(sql执行中的实际磁盘缓存)

与具体内存分配无关

5,sql审计

相关配置:

参数调整说明
log_min_duration_statementsql审计记录的标准,超过该时长的sql将被记录到日志文件。默认为-1,不记录超时sql。
log_statementnone默认,不记录;all-记录所有语句;ddl-记录所有数据定义语句;mod记录所有ddl和数据修改语句;
log_min_error_statement控制日志中是否记录导致数据库出现错误的SQL语句。默认为error

6,排查sql

-- 查看表结构 
SELECT column_name,data_type FROM information_schema.columns WHERE table_name = '表名'; 

-- 查看慢查询日志是否开启 
SHOW log_min_duration_statement; 

-- 设置慢查询日志 
ALTER DATABASE test SET log_min_duration_statement TO 10000; 

--慢sql 添加\watch 1监控
select query,wait_event_type,wait_event from pg_stat_activity 
where wait_event is not null and now()-state_change>interval '5 second';

--长wait事件
select query,wait_event_type,wait_event from pg_stat_activity where state='active' and wait_event is not null and now()-state_change>interval '5 second';

-- 查找经常被扫描的大型表 
SELECT schemaname, relname, seq_scan, seq_tup_read, idx_scan, seq_tup_read / seq_scan AS avg FROM pg_stat_user_tables WHERE seq_scan > 0 ORDER BY seq_tup_read DESC LIMIT 20; 

-- 跟踪 vacuum 进度 
SELECT * FROM pg_stat_progress_vacuum ;

7,pg统计收集器

比较耗费性能,默认关闭,可在postgresql.conf进行配置( stats_start_collector = true )。

这些表的具体说明参见:华为 openGauss (GaussDB) v2.1 使用手册

1>pg_stat_activity

常见应用


-- 展示在数据库中当前正在执行多少查询 
SELECT
	datname,
	COUNT ( * ) AS OPEN,
	COUNT ( * ) FILTER ( WHERE STATE = 'active' ) AS active,
	COUNT ( * ) FILTER ( WHERE STATE = 'idle' ) AS idle,
	COUNT ( * ) FILTER ( WHERE STATE = 'idle in transaction' ) AS idle_in_trans 
FROM
	pg_stat_activity
GROUP BY
	ROLLUP ( 1 )


-- 查看事务已经打开了多久
SELECT
	pid,
	xact_start,
	now( ) - xact_start AS duration 
FROM
	pg_stat_activity 
WHERE
	STATE LIKE'%transaction%' 
ORDER BY
	3 DESC;
	
-- 检查是否有长查询运行 
SELECT now() - query_start AS duration, datname, query FROM pg_stat_activity WHERE state = 'active' ORDER BY 1 DESC; 

--查询服务进程PID: 通过count(*)获取当前连接数
select pid,usename,client_addr,client_port from pg_stat_activity;
  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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 作为数据库产品原型,通过修改源码构筑自己的数据库,例如通过使用pg的sql解析器,省去自己编写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形式发布包。第十五课发布数据库引擎:大型项目迁移到自主研发数据库中,数据库层面的功能完善需求分析与设计
数据库在线学习的数据字典是指在数据库学习过程中,可以在线查看和了解数据库中各个对象的结构、属性和关系的工具或功能。通过数据字典,可以方便地获取数据库中表、视图、索引、约束等对象的详细信息,包括列名、数据类型、长度、索引类型等。这样可以帮助开发人员更好地理解数据库结构,进行数据库设计和查询优化等工作。 以下是一些常见的数据库在线学习的数据字典工具或功能: 1. Oracle数据库的数据字典:Oracle数据库提供了一系列的数据字典视图,如`ALL_TABLES`、`ALL_COLUMNS`、`ALL_INDEXES`等,可以通过查询这些视图来获取数据库对象的详细信息。 2. MySQL数据库的信息模式:MySQL数据库中有一个名为`information_schema`的数据库,其中包含了一系列的表,如`TABLES`、`COLUMNS`、`INDEXES`等,可以通过查询这些表来获取数据库对象的详细信息。 3. SQL Server数据库的系统视图:SQL Server数据库提供了一系列的系统视图,如`sys.tables`、`sys.columns`、`sys.indexes`等,可以通过查询这些视图来获取数据库对象的详细信息。 4. PostgreSQL数据库的系统目录:PostgreSQL数据库中有一些系统目录,如`pg_tables`、`pg_columns`、`pg_indexes`等,可以通过查询这些目录来获取数据库对象的详细信息。 通过使用这些工具或功能,可以方便地查看和了解数据库中的数据字典,帮助学习和开发人员更好地理解和使用数据库

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值