需要帮助了解NpgSQL连接打开过程

时间:2018-03-09 03:00:20

标签: postgresql npgsql

我一直在尝试优化使用NpgSQL 3.2.7连接到PostgreSQL 9.3数据库的Web服务。今天我安装了pgBouncer并注意到运行“select * from pg_stat_activity;”所有我的NpgSQL连接都列出了这个查询:

SELECT ns.nspname, a.typname, a.oid, a.typrelid, a.typbasetype,
CASE WHEN pg_proc.proname='array_recv' THEN 'a' ELSE a.typtype END AS type,
CASE
  WHEN pg_proc.proname='array_recv' THEN a.typelem
  WHEN a.typtype='r' THEN rngsubtype
  ELSE 0
END AS elemoid,
CASE
  WHEN pg_proc.proname IN ('array_recv','oidvectorrecv') THEN 3    /* Arrays last */
  WHEN a.typtype='r' THEN 2                                        /* Ranges before */
  WHEN a.typtype='d' THEN 1                                        /* Domains before */
  ELSE 0                                                           /* Base types first */
END AS ord
FROM pg_type AS a
JOIN pg_namespace AS ns ON (ns.oid = a.typnamespace)
JOIN pg_proc ON pg_proc.oid = a.typreceive
LEFT OUTER JOIN pg_type AS b ON (b.oid = a.typelem)
LEFT OUTER JOIN pg_range ON (pg_range.rngtypid = a.oid) 
WHERE
  (
    a.typtype IN ('b', 'r', 'e', 'd') AND
    (b.typtype IS NULL OR b.typtype IN ('b', 'r', 'e', 'd'))  /* Either non-array or array of supported element type */
  ) 

当我在pgAdmin中运行此查询时,需要3到5秒才能完成第二次运行它时应该缓存所有内容。当我以交互方式运行我的代码时,在Web服务中执行第一个打开命令调用需要3到5秒。

每次创建连接时都会运行吗?在我看来,这是一个昂贵的查询,以获得一些相对静态的数据。如果每次创建连接时都必须运行,那么是否有人建议如何在Web服务中构建此连接?对于每次调用Web服务,3到5秒的开销就太大了。使用池对是否运行此查询有影响吗?

增加:03/14/2018 这些是我在创建表以保存类型查询结果后看到的日志条目。它成功运行,后来由于某种原因无法找到表。

2018-03-14 15:35:42 EDT LOG:持续时间:0.715毫秒解析:从“公共”选择nspname,typname,oid,typrelid,typbasetype,type,elemoid,ord。“npgsqltypes”

2018-03-14 15:35:42 EDT LOG:持续时间:0.289 ms绑定:从“public”选择nspname,typname,oid,typrelid,typbasetype,type,elemoid,ord。“npgsqltypes”

2018-03-14 15:35:42 EDT LOG:执行:从“public”中选择nspname,typname,oid,typrelid,typbasetype,type,elemoid,ord。“npgsqltypes”

2018-03-14 15:35:42 EDT LOG:持续时间:0.391毫秒

2018-03-14 15:35:44 EDT ERROR:第71个字符中不存在关系“public.npgsqltypes”

2018-03-14 15:35:44 EDT声明:从“公共”中选择nspname,typname,oid,typrelid,typbasetype,type,elemoid,ord。“npgsqltypes”

2018-03-14 15:35:44 EDT LOG:声明:DISCARD ALL

2018-03-14 15:35:44 EDT LOG:持续时间:0.073毫秒

增加:03/15/2018

解释类型查询的输出:

Sort  (cost=3015139.78..3018795.67 rows=1462356 width=213)
  Sort Key: (CASE WHEN (pg_proc.proname = ANY ('{array_recv,oidvectorrecv}'::name[])) THEN 3 WHEN (a.typtype = 'r'::"char") THEN 2 WHEN (a.typtype = 'd'::"char") THEN 1 ELSE 0 END)
  ->  Hash Left Join  (cost=920418.37..2779709.53 rows=1462356 width=213)
        Hash Cond: (a.oid = pg_range.rngtypid)
        ->  Hash Join  (cost=920417.24..2752289.21 rows=1462356 width=209)
              Hash Cond: ((a.typreceive)::oid = pg_proc.oid)
              ->  Hash Join  (cost=919817.78..2724270.58 rows=1462356 width=149)
                    Hash Cond: (a.typnamespace = ns.oid)
                    ->  Hash Left Join  (cost=919305.50..2687199.40 rows=1462356 width=89)
                          Hash Cond: (a.typelem = b.oid)
                          Filter: (((a.typtype = ANY ('{b,r,e,d}'::"char"[])) AND ((b.typtype IS NULL) OR (b.typtype = ANY ('{b,r,e,d}'::"char"[])))) OR ((a.typname = ANY ('{record,void}'::name[])) AND (a.typtype = 'p'::"char")))
                          ->  Seq Scan on pg_type a  (cost=0.00..694015.89 rows=13731889 width=89)
                          ->  Hash  (cost=694015.89..694015.89 rows=13731889 width=5)
                                ->  Seq Scan on pg_type b  (cost=0.00..694015.89 rows=13731889 width=5)
                    ->  Hash  (cost=388.79..388.79 rows=9879 width=68)
                          ->  Seq Scan on pg_namespace ns  (cost=0.00..388.79 rows=9879 width=68)
              ->  Hash  (cost=465.87..465.87 rows=10687 width=68)
                    ->  Seq Scan on pg_proc  (cost=0.00..465.87 rows=10687 width=68)
        ->  Hash  (cost=1.06..1.06 rows=6 width=8)
              ->  Seq Scan on pg_range  (cost=0.00..1.06 rows=6 width=8)

1 个答案:

答案 0 :(得分:1)

你是对的,这个查询由Npgsql发出,用于从PostgreSQL后端加载所有类型 - 不同的数据库可以有不同的数据类型(由于扩展,用户定义的类型等)。

但是,此查询仅在与特定数据库的第一个物理连接上发送,由其连接字符串标识。换句话说,如果您连接到同一个数据库X次 - 到同一个连接字符串 - 您应该只看到此查询被发送一次。 Npgsql在内部缓存此信息。我刚刚确认这是3.2.7中的行为,您是否看到了其他内容?