【问题标题】:Index a view of a join with Postgresql?使用 Postgresql 索引连接视图?
【发布时间】:2012-01-16 15:57:10
【问题描述】:

我有一个 select 语句,可以从更复杂的视图中进行非常简单的查询:

我有一个相当直接的选择语句....

    SELECT
          uid
    FROM userpermissions
    WHERE
            uid         = :whoami
        AND
            application = :application
        AND
            subsystem   = :subsystem
    ;

而且我的观点只是 ints 和 varchars,而是四个表的连接(可能是真正的问题)。

                       View "public.userpermissions"
   Column    |          Type          | Modifiers | Storage  | Description
-------------+------------------------+-----------+----------+-------------
 uid         | integer                |           | plain    |
 gid         | integer                |           | plain    |
 sid         | integer                |           | plain    |
 name        | character varying(128) |           | extended |
 application | character varying(128) |           | extended |
 subsystem   | character varying(128) |           | extended |
View definition:
 SELECT users.uid, groups.gid, groupaccess.sid, groups.name, subsystems.application, subsystems.subsystem
   FROM users
   JOIN groups ON groups.gid = users.gid
   JOIN groupaccess ON groups.gid = groupaccess.gid
   JOIN subsystems ON subsystems.sid = groupaccess.sid;

我不确定如何有效地更新视图以使我的查询更有效,因为它们现在大约需要 1-4 秒,在某些情况下最多需要 8 秒。

我的另一个想法是使用内存缓存,但这感觉像是解决视图效率低下问题的创可贴。

这是选择的个人资料:

                                                        QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=1.18..4.54 rows=1 width=4) (actual time=0.043..0.043 rows=0 loops=1)
   Join Filter: (groups.gid = users.gid)
   ->  Nested Loop  (cost=1.18..3.34 rows=1 width=8) (actual time=0.040..0.040 rows=0 loops=1)
         ->  Hash Join  (cost=1.18..2.78 rows=1 width=4) (actual time=0.039..0.039 rows=0 loops=1)
               Hash Cond: (groupaccess.sid = subsystems.sid)
               ->  Seq Scan on groupaccess  (cost=0.00..1.43 rows=43 width=8) (actual time=0.014..0.014 rows=1 loops=1)
               ->  Hash  (cost=1.17..1.17 rows=1 width=4) (actual time=0.017..0.017 rows=0 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 0kB
                     ->  Seq Scan on subsystems  (cost=0.00..1.17 rows=1 width=4) (actual time=0.015..0.015 rows=0 loops=1)
                           Filter: (((application)::text = 'LoginLink'::text) AND ((subsystem)::text = '1'::text))
         ->  Index Scan using groups_pkey on groups  (cost=0.00..0.55 rows=1 width=4) (never executed)
               Index Cond: (gid = groupaccess.gid)
   ->  Seq Scan on users  (cost=0.00..1.19 rows=1 width=8) (never executed)
         Filter: (uid = 2)
 Total runtime: 0.192 ms
(15 rows)

这完全让我感到困惑,因为当我使用 PHP 将其放入 PDO 时,查询需要几秒钟,而不是几分之一秒。

【问题讨论】:

  • 使用 pg_query 需要多长时间?而且,您的数据库服务器有多远?
  • DB 和 Web 是同一台机器。上面的命令行 psql 显示 0.192ms,当从 PHP 调用时显示 3.6
  • 0.192 ms 是在数据库服务器中的时间,但是如果使用 PDO 函数的 PHP 实例的函数 pg_query,需要多长时间?
  • 使用 PDO,查询耗时 0.09 秒。我的代码中没有 pg_query。现在我更困惑了……我认为查询根本不是我的问题。
  • DB 和 Web 是同一台机器,但你是从另一台机器调用 PHP 脚本吗?我唯一能想到的就是你的网络可能有延迟。

标签: sql performance postgresql


【解决方案1】:

视图对性能没有帮助。简化事情,授予特定权利等只是一件好事。但它对查询性能没有任何好处。

您可以尝试删除中间人(视图)并使用以下查询:

SELECT u.uid
FROM   users u
JOIN   groupaccess g USING (gid)
JOIN   subsystems  s USING (sid)
WHERE  u.uid = :whoami
  AND  s.application = :application
  AND  s.subsystem   = :subsystem;

这也削减了另一个中间人,即表groups,在您的场景中根本不需要它。 (除非用户的连接行可能丢失,这是不可能的。)

为了提高性能,您必须将其设为 materialized view,这完全是另一种野兽。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    相关资源
    最近更新 更多