test luasql's postgresql driver performance (not better than pgbench)

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:
测试数据库性能的方法很多, 例如使用pgbench, sysbench.
对PostgreSQL而言, pgbench是性能损失最小的一种测试工具, 本文将使用lua以及luasql驱动测试一下, 我们对比一下使用lua和pgbench测试的结果, 看看lua会带来多少性能损失.

本文测试环境 : 
Lua 5.2.3
CentOS 6.4 x64
PostgreSQL 9.3.1
CPU
model name      : Intel(R) Xeon(R) CPU           E5504  @ 2.00GHz
stepping        : 5
cpu MHz         : 1596.010


使用2号CPU启动lua, 单线程测试.  因为0号CPU负面影响太大, 影响测试结果.
测试结果
[root@db-172-16-3-150 lib]# taskset -c 2 lua
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
> luasql = require "luasql.postgres"
> env = assert(luasql.postgres())
> con = assert(env:connect("host=/ssd1/pg931/pg_root dbname=digoal user=digoal password=digoal port=1922"))
> print(con:execute([[select 10]]):fetch())
10
> print(con:execute([[select 11]]):fetch())
11
> function foo(cnt) 
>>  local var1 = os.time()
>>  for i = 1,cnt do
>>    con:execute([[select 10]])
>>  end
>>  return (os.time()-var1)
>> end
> print(foo(100))
0
> print(foo(100000))
8
> print(foo(1000000))
84
> print(1000000/84.0)
11904.761904762 TPS


测试过程中LUA的CPU开销 : 
 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  P COMMAND                                                              
 6767 root      20   0  169m 5740 2328 R 21.5  0.0   0:54.69 2 lua


pg_stat_activity输出, 连接为unix socket.
digoal=# select * from pg_stat_activity;
-[ RECORD 1 ]----+--------------------------------
datid            | 16386
datname          | digoal
pid              | 6793
usesysid         | 16523
usename          | digoal
application_name | 
client_addr      | 
client_hostname  | 
client_port      | -1
backend_start    | 2014-02-21 14:54:59.29801+08
xact_start       | 
query_start      | 2014-02-21 14:57:35.449137+08
state_change     | 2014-02-21 14:57:35.44919+08
waiting          | f
state            | idle
query            | select 10


同样使用2号CPU, 直接使用pgbench的测试结果 : 
pg931@db-172-16-3-150-> taskset -c 2 pgbench -M prepared -n -r -c 1 -j 1 -T 30 -f ./test.sql -U digoal digoal
transaction type: Custom query
scaling factor: 1
query mode: prepared
number of clients: 1
number of threads: 1
duration: 30 s
number of transactions actually processed: 430052
tps = 14335.022228 (including connections establishing)
tps = 14336.394217 (excluding connections establishing)
statement latencies in milliseconds:
        0.068411        select 10;

显然使用lua测试只有pgbench测试性能的83%. 损失了17%的性能.
这个问题显然不是来自循环, 因为循环一亿次差不多也只要1秒.

> function foo(cnt)                        
 local var1 = os.time()
 for i = 1,cnt do
   -- con:execute([[select 10]])
 end
 return (os.time()-var1)
end
> print(foo(100000000))
1

那么问题出在哪里呢? 经过了解, luasql不支持prepared sql, 
(Lua SQL still makes me very sad by lacking parameterized queries
though. Yes, it's better than nothing, Which backends can't support a
norrmalized form for the most common statements?
	DBMS's are very different in this aspect.

	PostgreSQL [1]:

PREPARE fooplan (int, text, bool, numeric) AS
    INSERT INTO foo VALUES($1, $2, $3, $4);
EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);

	MySQL [2]:

PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
SET @a = 3;
SET @b = 4;
EXECUTE stmt1 USING @a, @b;

	Oracle OCI8 [3]:

INSERT INTO emp VALUES
    (:empno, :ename, :job, :sal, :deptno)

	I think LuaSQL should not define any of these forms, thus exposing
the incompatibilities between the databases.  Anyway, to offer an API
for prepared statements, LuaSQL must define a _standard_ way to declare,
bind the values and execute a prepared statement.  We have discussed that
before, but anyone had time to spend on that front :-(

	Regards,
		Tomás
LuaDBI [1] has prepared statements support built into the API. For the couple databases I have used in on, it appears to work great for me.
-Josh

[1] http://code.google.com/p/luadbi/

使用stap可以跟踪到这个现象
详见

stap -e '
probe process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__start") {
  println(pn(), user_string($arg1), pid())
}
probe process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__parse__start") {
  println(pn(), user_string($arg1), pid())
}
probe process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__rewrite__start") {
  println(pn(), user_string($arg1), pid())
}
probe process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__plan__start") {
  println(pn(), pid())
}
probe process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start") {
  println(pn(), pid())
}'

结果很明显, 没有使用prepared sql.
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__start")select 108312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__parse__start")select 108312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__rewrite__start")select 108312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__plan__start")8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8312
... 略 


那么使用postgresql原生的prepared看看性能会不会有改观 : 
> con:execute([[prepare p(int) as select $1]])
> print(con:execute([[execute p(1)]]):fetch())
1
> print(con:execute([[execute p(99)]]):fetch())
99
> function foo(cnt) 
 local var1 = os.time()
 for i = 1,cnt do
   con:execute([[execute p(10)]]) 
 end
 return (os.time()-var1)
end
> print(foo(1000000))
92

情况并没有好转, 原因是依旧没有使用prepared sql. 那么使用luasql这个驱动和直接使用pgbench测试的性能差异这么明显原因就在这里了.
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__start")prepare p(int) as select $18312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__parse__start")prepare p(int) as select $18312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__rewrite__start")prepare p(int) as select $18312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__start")execute p(10)8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__parse__start")execute p(10)8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__rewrite__start")execute p(10)8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__plan__start")8312
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8312
... 略

而使用pgbench的-M prepared则显然用了prepared sql.
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__parse__start")select 10;8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__plan__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
process("/home/pg931/pgsql9.3.1/bin/postgres").mark("query__execute__start")8495
... 略


我后面将再测试一下luapgsql, luadbi这几个驱动看看性能如何.

[参考] 5.  http://blog.163.com/digoal@126/blog/static/1638770402013916101117367/
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
关系型数据库 测试技术 数据库
PostgreSQL数据库压力测试工具pgbench简单应用
PG数据库提供了一款轻量级的压力测试工具叫pgbench,其实就是一个编译好后的扩展性的可执行文件。
2713 0
|
5月前
|
SQL 关系型数据库 测试技术
postgresql|数据库|数据库测试工具pgbench之使用
postgresql|数据库|数据库测试工具pgbench之使用
96 0
|
SQL 关系型数据库 测试技术
PostgreSQL pgbench tpcb 海量数据库测试 - 分区表测试优化
标签 PostgreSQL , pgbench , tpcb 背景 pgbench是PG的一款测试工具,内置的测试CASE为tpcb测试。同时支持用户自己写测试CASE。 大量自定义CASE参考 https://github.com/digoal/blog/blob/master/201711/readme.md 当我们使用tpcb测试CASE时,如果生成的数据量过于庞大,例如我最近在生成1万亿的CASE,可以考虑使用分区表,但是目前PG内置分区表的性能在分区非常多时,使用PREPARED STATEMENT会导致性能下降。
1853 0
|
SQL 关系型数据库 测试技术
PostgreSQL pgbench tpcb 数据生成与SQL部分源码解读
标签 PostgreSQL , pgbench , tpcb 背景 pgbench是PG的一款测试工具,内置的测试CASE为tpcb测试。同时支持用户自己写测试CASE。 大量自定义CASE参考 https://github.com/digoal/blog/blob/master/201711/readme.md 本文为pgbench 内置tpcb的解读。
1629 0
|
物联网 关系型数据库 数据库
|
关系型数据库 测试技术 PostgreSQL
|
SQL 关系型数据库 PostgreSQL
|
SQL Java 关系型数据库
PostgreSQL jdbc driver的一个不完善之处
公司一个产品在上线到云以后,运行一段时间就会提示获取数据库连接失败,用 select * from pg_stat_activity; 查看所有连接,发现有很多连接最后一次执行的SQL语句是 SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typspace = n.oid)  WHERE n.nspname  != 'pg_toast',经确认在程序中没有任何一处执行了该SQL。
1284 0