我有一个 SELECT
语句,它从一个更复杂的 View 进行一个非常简单的查询:
我有一个相当直接的选择语句:
SELECT uid
FROM userpermissions
WHERE uid = :whoami
AND application = :application
AND subsystem = :subsystem
;
而我的观点只是 int 和 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;
我不确定如何更改 View 以使我的查询更有效率,因为它们现在大约需要 1-4 秒,在某些情况下最多需要 8 秒。
我的另一个想法是使用内存缓存,但这感觉像是解决 View 效率低下问题的创可贴解决方案。
这是 EXPLAIN ANALYZE
的输出:
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 时,查询只需要几秒钟,而不是几分之一秒。
最佳答案
View 对性能没有帮助。简化事情、授予特定权利等只是好事。但它对查询性能没有任何好处。
您可以尝试去掉中间人( View )并使用此查询:
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 ,这是完全不同的野兽。
加上各个基础表(和/或物化 View )上的拟合索引。
关于sql - 索引连接查询的 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8882593/