论云数据库编程能力的重要性

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 云为我们提供了便利,降低了开发和运维的成本。但是也必须思考一个问题,我们的云组件之间的的网络延迟?(相比较局域网的服务器和服务器之间)你可以用各种方法测试验证一下。以往我们把数据放在数据库,数据库只提供简单的增删改查,大部分的业务逻辑放在应用服务器来完成。但是在云时代,如果我们还这样的话,应用服务.

云为我们提供了便利,降低了开发和运维的成本。
但是也必须思考一个问题,我们的云组件之间的的网络延迟?
(相比较局域网的服务器和服务器之间)
你可以用各种方法测试验证一下。
以往我们把数据放在数据库,数据库只提供简单的增删改查,大部分的业务逻辑放在应用服务器来完成。
但是在云时代,如果我们还这样的话,应用服务器和数据库间如果多次交互,会浪费大量的时间。
我们应该充分利用数据库的编程能力,例如PostgreSQL,是一个功能非常强大的数据库,我们完全可以把业务逻辑放在数据库处理,
例如使用plv8, plpython, plpgsql, plperl, pltcl等函数语言,
数据类型支持也非常的丰富,例如jsonb, GIS, text, 异构类型,Key-Value类型...等,
索引支持btree, hash, gin , gist, spgist, brin等索引类型,
SQL语法层面支持 窗口查询,递归查询,grouping set, 等高级语法。
JOIN方面,支持hash join , merge join , nestloop join ,
优化器方面,支持自定义成本因子, CBO , 遗传算法等。
另外PostgreSQL更强大之处,可以利用GPU加速运算,包括隐式加速,也可以显示加速。
隐式指数据库自身提供的custom scan provider编程接口,已经有实现了的插件。
显式,指的是过程语言和CUDA的结合,例如PyCUDA。
还可以用Julia来方便的实现并行编程。
PostgreSQL完全可以满足大多数业务的需求。

功能如此强大的数据库,只用来做增删改查,是不是有点浪费呢,充分利用它的功能,当网络是瓶颈的时候,让业务逻辑和数据靠近,可以大大提升效率,降低RT,提升业务系统的用户体验。

关于云端网络延迟,可以参考我在前几天写的几篇文档。
PostgreSQL 网络延迟定量分析
https://yq.aliyun.com/articles/35176

使用sysbench测试阿里云RDS PostgreSQL性能
(内容中包含了如何测试云数据库的网络延迟)
https://yq.aliyun.com/articles/35517

本文还会利用sysbench来佐证一下,使用数据库服务端编程后,带来的性能提升是多么明显。
测试环境依旧是阿里云RDS PostgreSQL,ECS是32核的机器,与RDS PG在同一机房。

步骤
购买RDS PG数据库实例
创建数据库用户
购买同机房,与RDS PG同VPC网络ECS或者同经典网络的ECS
在ECS端安装PostgreSQL客户端

useradd digoal  
su - digoal  

wget https://ftp.postgresql.org/pub/source/v9.5.2/postgresql-9.5.2.tar.bz2  
tar -jxvf postgresql-9.5.2.tar.bz2  
cd postgresql-9.5.2  
./configure --prefix=/home/digoal/pgsql9.5  
gmake world -j 16  
gmake install-world -j 16  

vi ~/env_pg.sh  
export PS1="$USER@`/bin/hostname -s`-> "  
export PGPORT=1921  
export LANG=en_US.utf8  
export PGHOME=/home/digoal/pgsql9.5  
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH  
export DATE=`date +"%Y%m%d%H%M"`  
export PATH=$PGHOME/bin:$PATH:.  
export MANPATH=$PGHOME/share/man:$MANPATH  
export PGHOST=$PGDATA  
export PGUSER=postgres  
export PGDATABASE=postgres  
alias rm='rm -i'  
alias ll='ls -lh'  
unalias vi  

. ~/env_pg.sh  

安装sysbench(from github)

cd ~  

git clone https://github.com/digoal/sysbench.git  

并行初始化测试数据
初始化256张表,每张表100万数据。

cd sysbench/sysbench

./sysbench_pg --test=lua/parallel_init_pg.lua \  
  --db-driver=pgsql \  
  --pgsql-host=xxx.xxx.xxx.xxx \  
  --pgsql-port=3432 \  
  --pgsql-user=digoal \  
  --pgsql-password=pwd \  
  --pgsql-db=postgres \  
  --oltp-tables-count=256 \  
  --oltp-table-size=1000000 \  
  --num-threads=256 \  
  cleanup  

./sysbench_pg --test=lua/parallel_init_pg.lua \  
  --db-driver=pgsql \  
  --pgsql-host=xxx.xxx.xxx.xxx \  
  --pgsql-port=3432 \  
  --pgsql-user=digoal \  
  --pgsql-password=pwd \  
  --pgsql-db=postgres \  
  --oltp-tables-count=256 \  
  --oltp-table-size=1000000 \  
  --num-threads=256 \  
  run  

表结构和数据样本如下

postgres=# \d sbtest1
                        Unlogged table "public.sbtest1"
 Column |      Type      |                      Modifiers                       
--------+----------------+------------------------------------------------------
 id     | integer        | not null default nextval('sbtest1_id_seq'::regclass)
 k      | integer        | 
 c      | character(120) | not null default ''::bpchar
 pad    | character(60)  | not null default ''::bpchar
Indexes:
    "sbtest1_pkey" PRIMARY KEY, btree (id)
    "k_1" btree (k)

postgres=# select * from sbtest1 limit 5;
 id |   k    |                                                            c                                                             |                             pad                              
----+--------+--------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------
  1 | 927400 | 78247013700-08372511066-37272961232-38016471864-11589387900-80841931510-50966088603-62786739920-93329627701-94363926684  | 20366050401-55867147298-47128473450-44371584107-36273281249 
  2 | 462112 | 33336348704-49028541945-04338357184-44674729632-69224541153-27063217868-14496534686-77928030196-63919798937-80588593810  | 38824762880-21605093266-59283997376-03159087192-70078005827 
  3 | 609690 | 17141976536-38472427836-27892280734-53859074932-31683911066-84549350288-65797420080-49379319521-63297303760-61130825562  | 36249349424-23238674070-77120648190-02671383694-80399189992 
  4 | 442570 | 67075106316-33193756800-10093726800-79829712284-63470268100-62589769080-83382855836-21662325414-74934263415-54280518945  | 73517378377-96791797586-54757886848-05144609036-20409864730 
  5 | 126743 | 21608327653-47776651750-16637007643-12991848186-40427635184-24941570285-23769806501-34607807466-88813292380-75665466083  | 06891362272-65143041120-84598756285-94704681508-91545142862 
(5 rows)

测试包含SQL如下,其中第一条SQL执行10次 :

   -- select c from tbl where id = $1;  --  执行10次  
   -- select id,k,c,pad from tbl where id in ($1,...$n);  
   -- select c from tbl where id between $1 and $2;  
   -- select sum(k) from tbl where id between $1 and $2;  
   -- select c from tbl where id between $1 and $2 order by c;  
   -- select distinct c from tbl where id between $1 and $2 order by c;  
   -- update tbl set k=k+1 where id = $1;  
   -- update tbl set c=$2 where id = $1;  
   -- delete from tbl where id = $1;  
   -- insert into tbl(id, k, c, pad) values ($1,$2,$3,$4);  

首先 测试不使用服务端编程时的性能, 分别测试16并发和256并发

./sysbench_pg --test=lua/oltp_pg.lua \  
  --db-driver=pgsql \  
  --pgsql-host=xxx.xxx.xxx.xxx \  
  --pgsql-port=3432 \  
  --pgsql-user=digoal \  
  --pgsql-password=pwd \  
  --pgsql-db=postgres \  
  --oltp-tables-count=16 \  
  --oltp-table-size=1000000 \  
  --num-threads=16 \  
  --max-time=120  \  
  --max-requests=0 \  
  --report-interval=1 \  
  run  

./sysbench_pg --test=lua/oltp_pg.lua \  
  --db-driver=pgsql \  
  --pgsql-host=xxx.xxx.xxx.xxx \  
  --pgsql-port=3432 \  
  --pgsql-user=digoal \  
  --pgsql-password=pwd \  
  --pgsql-db=postgres \  
  --oltp-tables-count=256 \  
  --oltp-table-size=1000000 \  
  --num-threads=256 \  
  --max-time=120  \  
  --max-requests=0 \  
  --report-interval=1 \  
  run  

测试结果
16并发
tps 248.27
qps 4717.13
256并发
tps 1243.61
qps 23628.59

然后 测试使用服务端编程时的性能, 分别测试16并发和256并发

./sysbench_pg --test=lua/oltp_pg_udf.lua \  
  --db-driver=pgsql \  
  --pgsql-host=xxx.xxx.xxx.xxx \  
  --pgsql-port=3432 \  
  --pgsql-user=digoal \  
  --pgsql-password=pwd \  
  --pgsql-db=postgres \  
  --oltp-tables-count=16 \  
  --oltp-table-size=1000000 \  
  --num-threads=16 \  
  --max-time=120  \  
  --max-requests=0 \  
  --report-interval=1 \  
  run  

./sysbench_pg --test=lua/oltp_pg_udf.lua \  
  --db-driver=pgsql \  
  --pgsql-host=xxx.xxx.xxx.xxx \  
  --pgsql-port=3432 \  
  --pgsql-user=digoal \  
  --pgsql-password=pwd \  
  --pgsql-db=postgres \  
  --oltp-tables-count=256 \  
  --oltp-table-size=1000000 \  
  --num-threads=256 \  
  --max-time=120  \  
  --max-requests=0 \  
  --report-interval=1 \  
  run  

测试结果
16并发
tps 1533.44
qps 29135.36
256并发
tps 1684.45
qps 32004.55

从测试数据可以非常明显的看到,RT对小事务的影响非常大(单个连接TPS只有 15.56,交互次数越多TPS越低)。
使用服务端编程,可以大大的规避网络问题,对于交互较多的高并发小事务起到的效果非常棒。
在所有的关系数据库中,PostgreSQL支持的服务端编程语言应该是最丰富的,例如C,Python,java,javascript, Lua, perl, tcl, perl, ......。
1

相关实践学习
2分钟自动化部署人生模拟器
本场景将带你借助云效流水线Flow实现人生模拟器小游戏的自动化部署
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
Java 数据库连接 网络安全
JDBC数据库编程(java实训报告)
这篇文章是关于JDBC数据库编程的实训报告,涵盖了实验要求、实验环境、实验内容和总结。文中详细介绍了如何使用Java JDBC技术连接数据库,并进行增删改查等基本操作。实验内容包括建立数据库连接、查询、添加、删除和修改数据,每个部分都提供了相应的Java代码示例和操作测试结果截图。作者在总结中分享了在实验过程中遇到的问题和解决方案,以及对Java与数据库连接操作的掌握情况。
JDBC数据库编程(java实训报告)
|
3月前
|
存储 数据库 Python
python的对象数据库ZODB的使用(python3经典编程案例)
该文章介绍了如何使用Python的对象数据库ZODB来进行数据存储,包括ZODB的基本操作如创建数据库、存储和检索对象等,并提供了示例代码。
47 0
|
3月前
|
JSON NoSQL 数据库
和SQLite数据库对应的NoSQL数据库:TinyDB的详细使用(python3经典编程案例)
该文章详细介绍了TinyDB这一轻量级NoSQL数据库的使用方法,包括如何在Python3环境中安装、创建数据库、插入数据、查询、更新以及删除记录等操作,并提供了多个编程案例。
132 0
|
4月前
|
存储 SQL 数据库
|
4月前
|
SQL 数据库 索引
SQL 编程最佳实践简直太牛啦!带你编写高效又可维护的 SQL 代码,轻松应对数据库挑战!
【8月更文挑战第31天】在SQL编程中,高效与可维护的代码至关重要,不仅能提升数据库性能,还降低维护成本。本文通过案例分析探讨SQL最佳实践:避免全表扫描,利用索引加速查询;合理使用JOIN,避免性能问题;避免使用`SELECT *`,减少不必要的数据传输;使用`COMMIT`和`ROLLBACK`确保事务一致性;添加注释提高代码可读性。遵循这些实践,不仅提升性能,还便于后期维护和扩展。应根据具体情况选择合适方法并持续优化SQL代码。
56 0
|
4月前
|
存储 SQL 数据库
【计算机三级数据库技术】第8章 数据库后台编程技术--附思维导图
本文介绍了数据库后台编程的关键技术,包括存储过程、用户定义函数、触发器和游标,并附有思维导图。
36 1
|
4月前
|
SQL 关系型数据库 MySQL
"Python与MySQL的浪漫邂逅:一键掌握增删改查,开启你的数据库编程之旅!"
【8月更文挑战第21天】Python因其简洁的语法和强大的库支持,成为连接数据库的首选工具。本文介绍如何使用Python连接MySQL数据库并执行基本操作。首先需安装`mysql-connector-python`库。通过配置连接信息建立数据库连接后,可利用`cursor.execute()`执行SQL语句进行数据的增删改查,并通过`commit()`提交更改。查询时使用`fetchall()`或`fetchone()`获取结果。记得处理异常及关闭连接以释放资源。掌握这些基础,有助于高效进行数据库编程。
69 0
|
6月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
75 3
|
6月前
|
SQL Java 关系型数据库
Java数据库编程的详细介绍
Java数据库编程的详细介绍
45 1
|
5月前
|
数据库管理 Python
在停车场管理系统工程中,我们可能会涉及到硬件设计、软件编程、数据库管理、用户界面设计等多个方面
在停车场管理系统工程中,我们可能会涉及到硬件设计、软件编程、数据库管理、用户界面设计等多个方面