对比测试了 openGauss、PostgreSQL、Oracle、MySQL 的CPU 指令数

我测试了在相同软硬件条件下,openGauss、PostgreSQL、Oracle 和 MySQL 的 CPU 指令数消耗对比,急着想知道结果的可以直接跳到最后一部分看结果。

1. 测试环境说明
  • 三种数据库均在同一台服务器上运行,内存 251G,CPU 为 Intel® Xeon® CPU E5-4650 v2 @ 2.40GHz(80核)。
  • 采样期间,测试语句均已完成预热,数据完全在内存中处理(Buffer Pool / Buffer Cache)。
  • 测试期间系统无其他高负载任务干扰。
2. Oracle Database 测试用例
2.1 建表与数据初始化

使用 CONNECT BY 语法进行高速数据生成。

复制代码
-- 清理环境
DROP TABLE t_cpu_test PURGE;

-- 建表并直接插入 100万 行数据
CREATE TABLE t_cpu_test NOLOGGING AS 
SELECT 
    rownum AS id, 
    rpad('X', 50, 'X') AS info, 
    sysdate AS created_time 
FROM 
    dual 
CONNECT BY 
    level <= 1000000;

-- 添加主键 (这对索引扫描至关重要)
ALTER TABLE t_cpu_test ADD CONSTRAINT pk_t_cpu_test PRIMARY KEY (id);

-- 收集统计信息
BEGIN 
    dbms_stats.gather_table_stats(ownname => USER, tabname => 'T_CPU_TEST'); 
END; 
/

-- 验证数据量
SELECT count(*) FROM t_cpu_test;
2.2 获取操作系统进程号 (SPID)

Oracle 为多进程架构,需要定位当前会话对应的 OS 进程 ID。

复制代码
SELECT p.spid, s.sid, s.serial#
FROM v$session s, v$process p
WHERE s.paddr = p.addr
AND s.sid = USERENV('SID');

本次测试获取到的 SPID: 64689

2.3 性能监控 (Linux Shell)

在操作系统侧执行 perf 命令,监控该进程在采样窗口内的 CPU 指令消耗。

复制代码
perf stat -e instructions:u -p 64689
2.4 Oracle 测试结果
复制代码
oracle@Yuan ~$ sudo perf stat -e instructions:u -p 64689
^C
 Performance counter stats for process id '64689':

           105,023      instructions:u                            

       2.411828207 seconds time elapsed

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3. openGauss 测试用例
3.1 建表与数据初始化

使用 PostgreSQL/openGauss 标准的 generate_series 函数生成数据。

SQL

复制代码
-- 清理环境
DROP TABLE IF EXISTS t_cpu_test;

-- 创建表结构
CREATE TABLE t_cpu_test (
    id integer,
    info varchar(50),
    created_time timestamp
);

-- 插入 100万 行数据
INSERT INTO t_cpu_test
SELECT
    n,
    rpad('X', 50, 'X'),
    now()
FROM
    generate_series(1, 1000000) as n;

-- 添加主键
ALTER TABLE t_cpu_test ADD PRIMARY KEY (id);

-- 收集统计信息
ANALYZE t_cpu_test;

-- 验证数据量
SELECT count(*) FROM t_cpu_test;

-- 预热/功能检查
SELECT * FROM t_cpu_test WHERE id = 1234;
3.2 获取操作系统线程号 (LWTID)

openGauss 为单进程多线程架构,需要通过 pg_thread_wait_status 视图关联查找当前会话底层的轻量级线程 ID (LWTID)。

复制代码
SELECT lwtid 
FROM pg_thread_wait_status 
WHERE sessionid = (SELECT sessionid FROM pg_stat_activity WHERE pid = pg_backend_pid());

本次测试获取到的 LWTID: 49936

3.3 性能监控 (Linux Shell)

在操作系统侧执行 perf 命令,监控该线程的 CPU 指令消耗。

复制代码
perf stat -e instructions:u -t 49936
3.4 openGauss 测试结果
复制代码
[root@dell ~]# perf stat -e instructions:u -t 49936
^C
 Performance counter stats for thread id '49936':

           302,869      instructions:u                           

       2.617229382 seconds time elapsed
4. PostgreSQL 9.2 测试用例

由于openGauss是基于PostgreSQL 9.2的基础上进行开发的,我们再增加在这个版本上的测试案例:

5. PostgreSQL 18.1 测试用例

PostgreSQL的命令基本和openGauss一致,只是获取进程号的指令不同:

复制代码
postgres=# SELECT pg_backend_pid();
 pg_backend_pid
----------------
          46606
(1 row)


[root@dell ~]# perf stat -e instructions:u -p 46606
^C
  Performance counter stats for process id '46606':

           108,145      instructions:u                           

       2.636957141 seconds time elapsed
6. MySQL 8.0 测试用例
6.1 建表与数据初始化

由于 MySQL 8.0 支持递归 CTE,可以使用以下语法快速生成 100 万行数据。

复制代码
-- 清理环境
DROP TABLE IF EXISTS t_cpu_test;

-- 创建表结构
CREATE TABLE t_cpu_test (
    id INT PRIMARY KEY,
    info VARCHAR(50),
    created_time DATETIME
) ENGINE=InnoDB;

-- 插入 100万 行数据 (设置递归深度限制以支持100万行)
SET SESSION cte_max_recursion_depth = 1000000;
INSERT INTO t_cpu_test
WITH RECURSIVE seq AS (
    SELECT 1 AS n
    UNION ALL
    SELECT n + 1 FROM seq WHERE n < 1000000
)
SELECT 
    n, 
    RPAD('X', 50, 'X'), 
    NOW() 
FROM seq;

-- 收集统计信息
ANALYZE TABLE t_cpu_test;
6.2 获取操作系统线程号 (LWTID)

在 MySQL 中,可以通过 performance_schema 获取当前连接对应的操作系统线程 ID。

复制代码
SELECT THREAD_OS_ID 
FROM performance_schema.threads 
WHERE PROCESSLIST_ID = CONNECTION_ID();

获取到的 LWTID 为: 30129

复制代码
[root@dell ~]# perf stat -e instructions:u -t 30129
^C
 Performance counter stats for thread id '30129':

            91,101      instructions:u                                

       3.136717427 seconds time elapsed
6.3 性能监控与结果示例

Bash

复制代码
# 在执行 SELECT * FROM t_cpu_test WHERE id = 123456 时进行采样
sudo perf stat -e instructions:u -t 74098
7. MariaDB 10.11 测试用例
7.1 建表与数据初始化

MariaDB 拥有非常高效的 sequence 存储引擎,生成数据最为快捷。

复制代码
-- 清理环境
DROP TABLE IF EXISTS t_cpu_test;

-- 创建表结构
CREATE TABLE t_cpu_test (
    id INT PRIMARY KEY,
    info VARCHAR(50),
    created_time DATETIME
) ENGINE=InnoDB;

-- 使用 MariaDB 特有的 seq 引擎插入 100万 行数据
INSERT INTO t_cpu_test
SELECT 
    seq, 
    RPAD('X', 50, 'X'), 
    NOW() 
FROM seq_1_to_1000000;

-- 收集统计信息
ANALYZE TABLE t_cpu_test;
7.2 获取操作系统线程号 (LWTID)

MariaDB 的方法与 MySQL 类似。

复制代码
 SELECT THREAD_OS_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = CONNECTION_ID();

获取到的 LWTID 为: 45642

7.3 性能监控与结果示例

Bash

复制代码
sudo perf stat -e instructions:u -t 45642
^C
 Performance counter stats for thread id '45642':

            84,393      instructions:u                                

       3.452852099 seconds time elapsed
8. 结果对比与分析

将各数据库在采样窗口内的数据汇总如下(以 PostgreSQL 18.1 为 1.00x 基准):

数据库版本 架构模式 CPU 指令数 (Instructions) 相对倍数
MariaDB 10.11 多线程 84,393 0.78x
MySQL 8.0 多线程 91,101 0.84x
Oracle 19c 多进程 105,023 0.97x
PostgreSQL 18.1 多进程 108,145 1.00x
PostgreSQL 9.2 多进程 119,349 1.10x
openGauss 6.0.3 多线程 302,869 2.80x

分析结论:

  • PostgreSQL 与 Oracle 的高度一致性。
  • PostgreSQL 18.1 (10.8万) 比 PostgreSQL 9.2 (11.9万) 的指令数更少,效率提升了约 10%。
  • MySQL 和 MariaDB 消耗的指令最少,它们都是索引组织表架构,执行计划中少一步。
  • openGauss 的指令数消耗大约是 PostgreSQL 原生版本 和 Oracle 的 3 倍。
相关推荐
CJi0NG1 小时前
【自用】MySQL-多表查询
数据库·mysql
雨落在了我的手上2 小时前
MySQL数据库基础(12):事务
数据库·mysql
2301_32241428044 小时前
基于web的校园失物招领管理系统59695-计算机毕设 原创(免费领源码+部署教程+开发环境)
mysql·nginx·php·apache·thinkphp·phpstudy·wampserver
这个DBA有点耶4 小时前
从INDEX到JOIN_ORDER:MySQL 8.0 Hint语法体系与五类实战场景
数据库·mysql·架构
夜雪一千4 小时前
MySQL 的ID用什么数据类型更好?主键ID选型实战
数据库·mysql
jnrjian4 小时前
Oracle PG data type 数据类型转化
oracle
斯内普吖5 小时前
(开源)线上花店系统实战指南 基于 Java + SSM + Vue + MySQL
java·vue.js·mysql·开源
Lucifer三思而后行6 小时前
Oracle library cache 等待怎么查?Lock、Pin、Mutex 一次讲清楚
oracle·lock
tryxr7 小时前
数据库如何通过 MVCC 实现隔离性
数据库·mysql·mvcc·隔离性