Rust中tokio-postgres驱动性能疑问及优化咨询
tokio-postgres 性能疑问与分析
测试代码
use tokio_postgres::{NoTls}; use tokio::time::Instant; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let (client, connection) = tokio_postgres::connect("...", NoTls).await?; tokio::spawn(async move { if let Err(e) = connection.await { eprintln!("connection error: {}", e); } }); let start = Instant::now(); let rows = client.query("EXPLAIN ANALYZE SELECT col1 FROM public.test_table WHERE col1 = '15000000'", &[]).await?; println!("> Query time: {:?}", start.elapsed()); let start_time_1 = Instant::now(); for row in rows { let value: &str = row.get(0); println!("{}", value); } println!("> Loop time: {:?} / Full time: {:?}", start_time_1.elapsed(), start.elapsed()); Ok(()) }
测试结果
> Query time: 2.2302ms Index Only Scan using idx_test_table_col1 on test_table (cost=0.43..4.45 rows=1 width=9) (actual time=0.093..0.094 rows=1 loops=1) Index Cond: (col1= '15000000'::text) Heap Fetches: 0 Planning Time: 0.658 ms Execution Time: 0.134 ms > Loop time: 2.3609ms / Full time: 4.8276ms
疑问与解答
1. 为何PostgreSQL执行时间仅0.134ms,tokio-postgres查询耗时却达2.2302ms?
PostgreSQL的Execution Time是数据库内部执行查询的纯计算时间,不包含任何网络传输和客户端处理开销。而tokio-postgres的Query time覆盖了从客户端发起请求到接收完所有结果的完整流程:
- TCP网络往返延迟(即使本地连接也有协议栈处理开销)
- PostgreSQL协议的多步消息交互(Parse、Bind、Execute、Sync等步骤的往返通信)
- 客户端对数据库返回消息的解析、内存分配与结构化处理
- Tokio异步 runtime 的调度开销
这些额外步骤的总耗时远大于数据库内部执行时间,属于正常现象。
2. 结果迭代为何耗时2.3609ms?能否加速?
这个耗时并非迭代结果本身的开销,核心原因是循环中调用的println!——这是同步的标准输出IO操作,速度极慢,会阻塞异步任务的执行。如果去掉println!,仅保留数据解析逻辑:
for row in rows { let _value: &str = row.get(0); }
迭代耗时会直接降到微秒级别。
tokio-postgres的Row.get()是类型安全的字段解析,本身开销极小,无需额外优化。
3. JDBC测试RPS达15705,Rust代码仅2850,是否Java性能更优?
不是,大概率是测试场景不一致导致的:
- 连接池配置与复用:确认Rust是否使用了连接池(如
bb8-tokio-postgres或deadpool-postgres),且连接数与JDBC一致。如果Rust测试用的是单连接串行执行,RPS自然远低于多连接并发的JDBC测试。 - 并发模型:JDBC的测试是10用户并发,Rust测试是否开启了同等数量的并发任务?异步代码需要充分利用并发才能发挥性能优势,单任务串行无法体现Rust的性能。
- 测试逻辑:JDBC是否使用了批量操作、prepared statement复用?Rust侧是否复用了查询的Prepared Statement?
- RPS计算方式:确认两者的RPS统计范围是否一致(是否包含连接建立时间、是否是稳定运行后的统计)。
调整测试场景,让Rust代码使用连接池并开启同等并发后,RPS应该能达到甚至超过JDBC的水平。
内容的提问来源于stack exchange,提问作者Dvashington
相关产品推荐
相关产品推荐

