PostgreSQL 9.6 内核优化 - sort 性能增强

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS SQL Server,基础系列 2核4GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介:

PostgreSQL 9.6 内核优化 - sort 性能增强

作者

digoal

日期

2016-10-09

标签

PostgreSQL , sort , 内核优化


背景

PostgreSQL 9.6在排序这块做了一些性能增强,前面一篇主要讲了排序算法的变更。

《PostgreSQL 9.6 内核优化 - sort性能增强(batch化quicksort代替replacement selection when work_mem small)》

本文针对另外几个SORT增强的点再简单介绍一下。

PostgreSQL 9.6 排序增强点

1. 文本排序性能增强,当相同的文本多次出现时,性能有所增强。

Speed up text sorts where the same string occurs multiple times (Peter Geoghegan)

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=0e57b4d8bd9674adaf5747421b3255b85e385534

Speed up text sorts where the same strings occur multiple times.

Cache strxfrm() blobs across calls made to the text SortSupport abbreviation routine.  
This can speed up sorting if the same string needs to be abbreviated many times in a row.

Also, cache the result of the previous strcoll() comparison, so that if we're asked to compare the same strings agin, we do need to call strcoll() again.

Perhaps surprisingly, these optimizations don't seem to hurt even when they don't help.  
memcmp() is really cheap compared to strcoll() or strxfrm().

Peter Geoghegan, reviewed by me.  

2. 对uuid,bytea,char(n)的排序性能增强,使用abb keys, 整型比较算法取代memcmp。

Speed up sorting of uuid, bytea, and char(n) fields by using "abbreviated" keys (Peter Geoghegan)

Support for abbreviated keys has also been added to the non-default operator classes text_pattern_ops, varchar_pattern_ops, and bpchar_pattern_ops.

Processing of ordered-set aggregates can also now exploit abbreviated keys.

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=a76ef15d9fc9207a0758e8d6f6700dc8c931a934

Add sort support routine for the UUID data type.

This introduces a simple encoding scheme to produce abbreviated keys:
pack as many bytes of each UUID as will fit into a Datum.  
On little-endian machines, a byteswap is also performed; 
the abbreviated comparator can therefore just consist of a simple 3-way unsigned integer comparison.

The purpose of this change is to speed up sorting data on a column of type UUID.

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=bfb54ff15a447fb22e9deae096e0d45b3e4bd56f

Make abbreviated key comparisons for text a bit cheaper.

If we do some byte-swapping while abbreviating, 
we can do comparisons using integer arithmetic rather than memcmp.

3. 并行创建索引(非堵塞式)的性能增强

Speed up CREATE INDEX CONCURRENTLY by treating TIDs as 64-bit integers during sorting (Peter Geoghegan)

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=b648b70342fbe712383e8cd76dc8f7feaba9aaa3

Speed up CREATE INDEX CONCURRENTLY's TID sort. 

Encode TIDs as 64-bit integers to speed up comparisons.   
This seems to speed things up on all platforms, but is even more beneficial when 8-byte integers are passed by value. 

Peter Geoghegan.  Design suggestions and review by Tom Lane.  
Review also by Simon Riggs and by me. 

测试例子

1. 高度重复文本排序

1000万记录

postgres=# create table test(id int, info text);
CREATE TABLE
postgres=# insert into test select generate_series(1,10000000), '111111111111111111111111111111111111111111111111111111111111';
INSERT 0 10000000

1.1 PostgreSQL 9.5

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from test order by info ;
                                                            QUERY PLAN                                                            
----------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=1854886.10..1879886.14 rows=10000017 width=65) (actual time=9035.319..10444.277 rows=10000000 loops=1)
   Output: id, info
   Sort Key: test.info
   Sort Method: external sort  Disk: 733144kB
   Buffers: shared hit=123457, temp read=91643 written=91643
   ->  Seq Scan on public.test  (cost=0.00..223457.17 rows=10000017 width=65) (actual time=0.007..1135.602 rows=10000000 loops=1)
         Output: id, info
         Buffers: shared hit=123457
 Planning time: 0.095 ms
 Execution time: 11151.855 ms
(10 rows)

排序耗时7.9秒

1.2 PostgreSQL 9.6

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from test order by info ;
                                                           QUERY PLAN                                                            
---------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=4544431.28..4612332.63 rows=27160540 width=9) (actual time=8141.378..9660.753 rows=10000000 loops=1)
   Output: id, info
   Sort Key: test.info
   Sort Method: external sort  Disk: 733144kB
   Buffers: shared hit=123457, temp read=91643 written=91643
   ->  Seq Scan on public.test  (cost=0.00..395062.40 rows=27160540 width=9) (actual time=0.011..1188.940 rows=10000000 loops=1)
         Output: id, info
         Buffers: shared hit=123457
 Planning time: 0.053 ms
 Execution time: 10387.210 ms
(10 rows)

排序耗时6.9秒

2. 离散文本排序

1000万记录

postgres=# create table test_rand(id int, info text);
CREATE TABLE
postgres=# insert into test_rand select generate_series(1,10000000), md5(random()::text);
INSERT 0 10000000

2.1 PostgreSQL 9.5

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from test_rand order by info ;
                                                              QUERY PLAN                                                               
---------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=1754736.47..1781195.02 rows=10583418 width=36) (actual time=21266.183..26347.778 rows=10000000 loops=1)
   Output: id, info
   Sort Key: test_rand.info
   Sort Method: external merge  Disk: 459464kB
   Buffers: shared hit=83334, temp read=150352 written=150352
   ->  Seq Scan on public.test_rand  (cost=0.00..189168.18 rows=10583418 width=36) (actual time=0.013..1363.646 rows=10000000 loops=1)
         Output: id, info
         Buffers: shared hit=83334
 Planning time: 0.069 ms
 Execution time: 27005.070 ms
(10 rows)

排序耗时19.9秒

2.2 PostgreSQL 9.6

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from test_rand order by info ;
                                                              QUERY PLAN                                                              
--------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=1658485.88..1683485.52 rows=9999858 width=37) (actual time=16424.010..21024.141 rows=10000000 loops=1)
   Output: id, info
   Sort Key: test_rand.info
   Sort Method: external merge  Disk: 459464kB
   Buffers: shared hit=83334, temp read=179142 written=179142
   ->  Seq Scan on public.test_rand  (cost=0.00..183332.58 rows=9999858 width=37) (actual time=0.011..1025.182 rows=10000000 loops=1)
         Output: id, info
         Buffers: shared hit=83334
 Planning time: 0.053 ms
 Execution time: 21691.354 ms
(10 rows)

排序耗时15秒

3. char(n)排序

1000万记录

postgres=# create table char_32(id char(32));
CREATE TABLE
postgres=# insert into char_32 select md5(random()::text) from generate_series(1,10000000);
INSERT 0 10000000

3.1 PostgreSQL 9.5

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from char_32 order by id;
                                                             QUERY PLAN                                                              
-------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=925778.75..936403.83 rows=4250034 width=132) (actual time=29156.470..35327.059 rows=10000000 loops=1)
   Output: id
   Sort Key: char_32.id
   Sort Method: external merge  Disk: 420408kB
   Buffers: shared hit=83339, temp read=137591 written=137591
   ->  Seq Scan on public.char_32  (cost=0.00..125834.34 rows=4250034 width=132) (actual time=0.009..1324.482 rows=10000000 loops=1)
         Output: id
         Buffers: shared hit=83334
 Planning time: 0.085 ms
 Execution time: 35961.840 ms
(10 rows)

排序耗时27.8秒

3.2 PostgreSQL 9.6

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from char_32 order by id;
                                                             QUERY PLAN                                                              
-------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=1658523.51..1683523.71 rows=10000080 width=33) (actual time=17423.580..22348.735 rows=10000000 loops=1)
   Output: id
   Sort Key: char_32.id
   Sort Method: external merge  Disk: 420432kB
   Buffers: shared hit=83339, temp read=163911 written=163911
   ->  Seq Scan on public.char_32  (cost=0.00..183334.80 rows=10000080 width=33) (actual time=0.019..1203.205 rows=10000000 loops=1)
         Output: id
         Buffers: shared hit=83336
 Planning time: 0.200 ms
 Execution time: 23013.343 ms
(10 rows)

排序耗时16.2秒

4. 非堵塞式创建索引

5000万随机数据

postgres=# create table curr_idx_test(id int);
CREATE TABLE
postgres=# insert into curr_idx_test select 50000000*random() from generate_series(1,50000000);
INSERT 0 50000000
postgres=# \dt+ curr_idx_test 
                         List of relations
 Schema |     Name      | Type  |  Owner   |  Size   | Description 
--------+---------------+-------+----------+---------+-------------
 public | curr_idx_test | table | postgres | 1729 MB | 
(1 row)

4.1 PostgreSQL 9.5

postgres=# set maintenance_work_mem='16GB';
SET
postgres=# \timing
Timing is on.
postgres=# create index CONCURRENTLY idx1_curr_idx_test on curr_idx_test(id);
CREATE INDEX
Time: 92591.646 ms

4.2 PostgreSQL 9.6

postgres=# set maintenance_work_mem='16GB';
SET
postgres=# \timing
Timing is on.
postgres=# create index CONCURRENTLY idx1_curr_idx_test on curr_idx_test(id);
CREATE INDEX
Time: 56483.672 ms

5. 堵塞式创建索引

5.1 PostgreSQL 9.5

postgres=# create index idx2_curr_idx_test on curr_idx_test(id);
CREATE INDEX
Time: 40733.880 ms

5.2 PostgreSQL 9.6

postgres=# create index idx2_curr_idx_test on curr_idx_test(id);
CREATE INDEX
Time: 40713.340 ms

结果对比

1. 高度重复文本排序(1000万记录)
PostgreSQL 9.5 排序耗时7.9秒
PostgreSQL 9.6 排序耗时6.9秒

2. 离散文本排序(1000万记录),quicksort的优化
PostgreSQL 9.5 排序耗时19.9秒
PostgreSQL 9.6 排序耗时15秒

3. char(n)排序(1000万记录)
PostgreSQL 9.5 排序耗时27.8秒
PostgreSQL 9.6 排序耗时16.2秒

4. 非堵塞式创建索引(5000万记录)
PostgreSQL 9.5 排序耗时92.6秒
PostgreSQL 9.6 排序耗时56.5秒

5. 堵塞式创建索引(5000万记录)
PostgreSQL 9.5 排序耗时40.7秒
PostgreSQL 9.6 排序耗时40.7秒

Count

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
4月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
10月前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
561 66
|
3月前
|
关系型数据库 MySQL 分布式数据库
Super MySQL|揭秘PolarDB全异步执行架构,高并发场景性能利器
阿里云瑶池旗下的云原生数据库PolarDB MySQL版设计了基于协程的全异步执行架构,实现鉴权、事务提交、锁等待等核心逻辑的异步化执行,这是业界首个真正意义上实现全异步执行架构的MySQL数据库产品,显著提升了PolarDB MySQL的高并发处理能力,其中通用写入性能提升超过70%,长尾延迟降低60%以上。
|
3月前
|
SQL 关系型数据库 PostgreSQL
CTE vs 子查询:深入拆解PostgreSQL复杂SQL的隐藏性能差异
本文深入探讨了PostgreSQL中CTE(公共表表达式)与子查询的选择对SQL性能的影响。通过分析两者底层机制,揭示CTE的物化特性及子查询的优化融合优势,并结合多场景案例对比执行效率。最终给出决策指南,帮助开发者根据数据量、引用次数和复杂度选择最优方案,同时提供高级优化技巧和版本演进建议,助力SQL性能调优。
265 1
|
4月前
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
3月前
|
固态存储 关系型数据库 数据库
从Explain到执行:手把手优化PostgreSQL慢查询的5个关键步骤
本文深入探讨PostgreSQL查询优化的系统性方法,结合15年数据库优化经验,通过真实生产案例剖析慢查询问题。内容涵盖五大关键步骤:解读EXPLAIN计划、识别性能瓶颈、索引优化策略、查询重写与结构调整以及系统级优化配置。文章详细分析了慢查询对资源、硬件成本及业务的影响,并提供从诊断到根治的全流程解决方案。同时,介绍了索引类型选择、分区表设计、物化视图应用等高级技巧,帮助读者构建持续优化机制,显著提升数据库性能。最终总结出优化大师的思维框架,强调数据驱动决策与预防性优化文化,助力优雅设计取代复杂补救,实现数据库性能质的飞跃。
465 0
|
6月前
|
缓存 关系型数据库 MySQL
ThinkPHP框架show columns引发mysql性能问题
ThinkPHP框架的show columns引发mysql性能问题,结尾有关闭方式。
198 13
|
6月前
|
关系型数据库 MySQL OLAP
无缝集成 MySQL,解锁秒级 OLAP 分析性能极限,完成任务可领取三合一数据线!
通过 AnalyticDB MySQL 版、DMS、DTS 和 RDS MySQL 版协同工作,解决大规模业务数据统计难题,参与活动完成任务即可领取三合一数据线(限量200个),还有机会抽取蓝牙音箱大奖!
|
7月前
|
SQL 关系型数据库 OLAP
云原生数据仓库AnalyticDB PostgreSQL同一个SQL可以实现向量索引、全文索引GIN、普通索引BTREE混合查询,简化业务实现逻辑、提升查询性能
本文档介绍了如何在AnalyticDB for PostgreSQL中创建表、向量索引及混合检索的实现步骤。主要内容包括:创建`articles`表并设置向量存储格式,创建ANN向量索引,为表增加`username`和`time`列,建立BTREE索引和GIN全文检索索引,并展示了查询结果。参考文档提供了详细的SQL语句和配置说明。
168 2
|
8月前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
1461 1

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多