Aekor

Aekor
专注于用户阅读体验的响应式博客主题
  1. 首页
  2. Blog
  3. 正文

同一个主键查询,六种数据库的 CPU 指令数差多少

2026-10-16 9487点热度 0人点赞 0条评论

比较数据库性能,大家习惯看耗时、看 QPS、看执行计划。这些指标都有个共同问题:受环境影响太大。缓存命中率、后台任务、CPU 频率抖动,任何一个都能让数字漂移。

指令数(instructions)是另一条路子。它统计的是一条 SQL 在用户态真正执行了多少条 CPU 指令,跟主频和调度关系小得多,适合横向比较“同一件事,谁做的无用功更少”。

我把 openGauss、PostgreSQL、Oracle、MySQL 和 MariaDB 放在同一台机器上,用 perf stat 采了一遍。

测试环境:MySQL 8.0 与 Oracle 性能优化相关书籍

测试环境

  • 内存 251G,CPU 为 Intel Xeon E5-4650 v2 @ 2.40GHz,80 核;
  • 所有数据库跑在同一台服务器上,测试期间没有其他高负载任务;
  • 采样前语句已完成预热,数据完全在 Buffer Pool / Buffer Cache 中处理,排除磁盘 IO 干扰。

测试语句统一为:一张 100 万行的表,主键 id,按主键做一次等值查询 SELECT * FROM t_cpu_test WHERE id = 123456。这是最简单的索引扫描路径,能把各家的执行器开销暴露得比较干净。

Oracle 19c:先找到会话对应的 OS 进程

Oracle 是多进程架构,要先拿到当前会话对应的 SPID,再对这个进程采样。

-- 建表并插入 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;
/

-- 定位当前会话的 OS 进程
SELECT p.spid, s.sid, s.serial#
FROM v$session s, v$process p
WHERE s.paddr = p.addr
  AND s.sid = USERENV('SID');
$ sudo perf stat -e instructions:u -p 64689
^C
    105,023      instructions:u
    2.411828207 seconds time elapsed
Oracle 19c 用 perf stat 采样会话进程的 CPU 指令数

openGauss 6.0.3:多线程,要找 LWTID

openGauss 是单进程多线程架构,perf 要跟的是线程号而不是进程号,通过 pg_thread_wait_status 关联。

CREATE TABLE t_cpu_test (
    id integer,
    info varchar(50),
    created_time timestamp
);

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 lwtid
FROM pg_thread_wait_status
WHERE sessionid = (SELECT sessionid FROM pg_stat_activity WHERE pid = pg_backend_pid());
# perf stat -e instructions:u -t 49936
^C
    302,869      instructions:u
    2.617229382 seconds time elapsed
openGauss 6.0.3 用 perf stat 采样 LWTID 的指令数

PostgreSQL:9.2 与 18.1 一起测

openGauss 基于 PostgreSQL 9.2 开发,所以我把 9.2 和 18.1 都拉进来做参照,顺便看看十几年间执行器优化了多少。

PostgreSQL 取进程号最简单,一条 SELECT pg_backend_pid() 就够。建表和 openGauss 完全一致。

postgres=# SELECT pg_backend_pid();
 pg_backend_pid
----------------
          46606

# perf stat -e instructions:u -p 46606
^C
    108,145      instructions:u
    2.636957141 seconds time elapsed
PostgreSQL 9.2 的 perf stat 采样结果,119349 条指令
PostgreSQL 18.1 的 perf stat 采样结果,108145 条指令

MySQL 8.0 与 MariaDB 10.11

两家都是多线程 + 索引组织表,取线程号的方法一样,从 performance_schema.threads 里按连接 ID 查 THREAD_OS_ID。

CREATE TABLE t_cpu_test (
    id INT PRIMARY KEY,
    info VARCHAR(50),
    created_time DATETIME
) ENGINE=InnoDB;

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;

SELECT THREAD_OS_ID
FROM performance_schema.threads
WHERE PROCESSLIST_ID = CONNECTION_ID();

MariaDB 有自带的 sequence 存储引擎,造数据更快,一行 seq_1_to_1000000 就够了。

INSERT INTO t_cpu_test
SELECT seq, RPAD('X', 50, 'X'), NOW()
FROM seq_1_to_1000000;
# MySQL 8.0
    91,101      instructions:u
    3.136717427 seconds time elapsed

# MariaDB 10.11
    84,393      instructions:u
    3.452852099 seconds time elapsed
MySQL 8.0 的 perf stat 采样结果,91101 条指令
MariaDB 10.11 的 perf stat 采样结果,84393 条指令

结果:以 PostgreSQL 18.1 为 1.00x

数据库版本架构模式CPU 指令数相对倍数
MariaDB 10.11多线程84,3930.78x
MySQL 8.0多线程91,1010.84x
Oracle 19c多进程105,0230.97x
PostgreSQL 18.1多进程108,1451.00x
PostgreSQL 9.2多进程119,3491.10x
openGauss 6.0.3多线程302,8692.80x

几个值得注意的点

PostgreSQL 和 Oracle 几乎打平。 一个是开源多进程,一个是商业库,在“一次主键等值查询”这条最朴素的路径上,指令数只差 3%。这说明两者的执行器开销在同一量级,差异更多体现在优化器选择和并发模型上,而不是单条语句的机械开销。

PostgreSQL 18.1 比 9.2 少约 10% 的指令。 十几年迭代,在这样一条简单查询上还能抠出 10%,说明执行器里确实有不少细碎的开销被逐步消掉了。这个数字不大,但方向很稳定。

MySQL 和 MariaDB 最省。 两者都是索引组织表,主键就是聚簇索引,等值查询直接在 B+ 树上定位到行,比堆表多一次回表少了步骤。MariaDB 又比 MySQL 少 7% 左右,和它的执行路径更短有关。

openGauss 是 PostgreSQL 的 2.8 倍。 这个差距远超预期。它跑的是同一套 SQL、同样的数据量,多出来的指令大概率来自线程模型、内存管理和额外的安全/审计钩子。指令数不等于性能,但它确实说明这条路径上有相当多的额外工作。

指令数只能回答“谁做的无用功更少”,回答不了“谁更快”。真实业务里的排序、连接、并行、锁竞争,都不是这一个数字能覆盖的。它的价值在于:把变量控制到最小之后,给你一个不受主频和缓存干扰的横截面。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: MySQL openGauss Oracle PostgreSQL 性能优化 数据库
最后更新:2026-10-16

Aekor

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

使用AI教程

  • API报错解决方案
  • API 基础知识
  • API Key 获取
  • 最新接入教程

分类

  • Blog
  • Oracle 数据库
  • TradingAgents-CN
  • 使用教程
  • 数据库

COPYRIGHT © 2026 Aekor. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang