sql - 为什么 PostgreSQL 查询在第一个新连接后的第一个请求中比在后续请求中慢?

标签 sql postgresql

为什么 PostgreSQL 查询在第一个新连接后的第一个请求中比在后续请求中慢?

使用几种不同的技术连接到 postgresql 数据库。第一个请求可能需要 1.5 秒。第二次完全相同的查询将花费 0.03 秒。打开我的应用程序的第二个实例(连接到同一个数据库),第一个请求需要 1.5 秒,第二个需要 0.03 秒。

由于我们使用的技术不同,它们在不同的点连接并使用不同的连接方法,所以我真的不认为这与我编写的任何代码有任何关系。

我认为在第一个请求之前打开连接不会做“所有事情”,因此该请求有一些开销。

因为我已经使用了数据库,并保持服务器正常运行,所有内容都在内存中,所以索引等应该不是问题。

编辑 解释 - 告诉我有关查询的信息,老实说查询看起来很不错(索引等)。我真的认为 postgresql 在第一次查询新连接时有一些开销。

我不知道如何证明/反驳这一点。如果我使用 PG Admin III(pgAdmin 版本 1.12.3),所有查询似乎都很快。我有第一个查询的任何其他工具都很慢。大多数时候它并没有明显变慢,如果是的话,我总是把它归结为用索引更新 ram。但这显然不是那样。如果我打开我的工具并执行任何其他返回结果的查询,那么第二个查询无论如何都会很快。如果第一个查询没有返回结果,那么第二个查询仍然很慢,然后第三个查询很快。

编辑2 尽管我不认为查询与延迟有任何关系(每个第一个查询都很慢)这里有两个运行 Explain (EXPLAIN ANALYZE) 的结果

 EXPLAIN ANALYZE 
 select * from company
 where company_id = 39

输出:

"Seq Scan on company  (cost=0.00..1.26 rows=1 width=54) (actual time=0.037..0.039 rows=1 loops=1)"
"  Filter: (company_id = 39)"
"Total runtime: 0.085 ms"

和:

EXPLAIN ANALYZE
select * from group_devices
where device_name ilike 'html5_demo'
and group_id in ( select group_id from manager_groups
where company_id in (select company_id from company where company_name ='TRUTHPT'))

输出:

"Nested Loop Semi Join  (cost=1.26..45.12 rows=1 width=115) (actual time=1.947..2.457 rows=1 loops=1)"
"  Join Filter: (group_devices.group_id = manager_groups.group_id)"
"  ->  Seq Scan on group_devices  (cost=0.00..38.00 rows=1 width=115) (actual time=0.261..0.768 rows=1 loops=1)"
"        Filter: ((device_name)::text ~~* 'html5_demo'::text)"
"  ->  Hash Semi Join  (cost=1.26..7.09 rows=9 width=4) (actual time=0.297..1.596 rows=46 loops=1)"
"        Hash Cond: (manager_groups.company_id = company.company_id)"
"        ->  Seq Scan on manager_groups  (cost=0.00..5.53 rows=509 width=8) (actual time=0.003..0.676 rows=469 loops=1)"
"        ->  Hash  (cost=1.26..1.26 rows=1 width=4) (actual time=0.035..0.035 rows=1 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Seq Scan on company  (cost=0.00..1.26 rows=1 width=4) (actual time=0.025..0.027 rows=1 loops=1)"
"                    Filter: ((company_name)::text = 'TRUTHPT'::text)"
"Total runtime: 2.566 ms"

最佳答案

我观察到相同的行为。如果我启动一个新连接,并多次运行查询,第一次执行比后续执行慢 25% 左右。 (这个查询已经在其他连接中运行过,我已经验证没有涉及磁盘 I/O。)我在第一次查询执行期间使用 perf 分析了这个过程,这是我发现的:

enter image description here

如您所见,大量时间花在了处理页面错误上。如果我分析第二次执行,则没有页面错误。 AFAICT,这些就是所谓的次要/软页面错误。当进程第一次访问共享内存中的页面时会发生这种情况。此时,进程需要将页面映射到它的虚拟地址空间(参见 https://en.wikipedia.org/wiki/Page_fault )。如果页面需要从磁盘读取,则称为主要/硬页面错误。

这个解释也符合我所做的其他观察:如果我稍后在同一个连接中运行不同的查询,第一次执行的开销似乎取决于与访问的数据有多少重叠第一次查询。

关于sql - 为什么 PostgreSQL 查询在第一个新连接后的第一个请求中比在后续请求中慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24065266/

相关文章:

mysql - 如何在MySQL中强制执行唯一约束?

php - MySQL外域搜索

mysql - 如何检查表中是否存在列?

sql - 如何设计数据库来保存Dominion卡?

sql - 多表一对一关系

java - 如何在执行.sql文件时出现oracle错误

php - MYSQL ON DUPLICATE KEY UPDATE问题

mysql - 使用 pgloader 将 MySQL 数据库转换为 Postgres 数据库

postgresql - DBeaver 和 PostgreSQL 中的串行数据类型问题

sql - 按多对多表分组