SQL查询优化:如何优化此搜索栏查询?

时间:2019-07-27 08:29:36

标签: sql postgresql amazon-cognito

先决条件:文档资源(ER图)为here

您好,我在Refactory方面苦苦挣扎,搜索栏查询需要执行更复杂的操作。

最初,当您不是“ root”组的成员时,查询将在数据库中搜索“ users”,并且仅检索“ root”用户(只有2个组:root和non-roots。这代表了由名为“ root”的布尔列组成)。但是现在该平台需要支持更多角色,我这样定义它们:

  • 'root'角色:该角色可以访问所有人的所有内容。此角色仅适用于开发人员和产品所有者。
  • “ group_admin”角色:该角色设置为该角色的用户成员可以访问附加到他的其他角色的成员的数据;
  • “ group_member”角色类型:仅表示用户是某个组的成员,但是他只能访问管理自己的数据。

例如: -如果用户已经附加了“ group_admin”角色和“ group1”角色,则该用户可以管理“ group1”角色成员的数据。 -如果用户已附加“ group2”角色,则该用户只能管理其数据。 -如果用户已附加了“ group-admin”,“ group1”和“ group2”角色,则他可以管理“ group1”和“ group2”成员的数据。 -如果用户具有“根”角色,则可以管理每个人的数据。

因此,正如您所看到的,用户管理的复杂性已经发生了很大变化。而且,重构也改变了数据模型和数据库实体。

正如我之前解释的,这些更改之一是用户搜索栏。 而且我认为该产品发布后,新查询的效果将不佳

这是上一个查询:

EXPLAIN ANALYSE SELECT * FROM users
        WHERE name ILIKE '%' || ? || '%'
        AND root = true

这是新的查询:

EXPLAIN ANALYSE WITH selected AS (
    SELECT DISTINCT group_enrollments.user_id, record_value
    FROM group_enrollments, user_attributes
    WHERE
          user_attributes.user_id = group_enrollments.user_id AND
          record_name = 'Name' AND
          group_name = ? AND
          record_value IN (
              SELECT record_value
              FROM group_enrollments, user_attributes
              WHERE
                    user_attributes.user_id = group_enrollments.user_id AND
                    record_name = 'Name' AND
                    group_name = 'group_admin'
          )
UNION ALL (
    SELECT group_enrollments.user_id, record_value
    FROM group_enrollments, user_attributes
    WHERE user_attributes.user_id = group_enrollments.user_id AND
          record_name = 'Name' AND
          group_name = 'root'))
SELECT user_id, record_value
FROM selected
WHERE selected.record_value ILIKE '%' || ? || '%'
ORDER BY record_value ;

如您所见,查询增长了很多,而我对(查询计划程序的)长度和性能感到不满意

事实上。为了将AWS Cognito集成为身份提供商以增强安全性和合规性,也需要使用此重构。

以下是两者的查询计划:

  • 旧的:
Seq Scan on users  (cost=0.00..2.56 rows=1 width=132) (actual time=0.016..0.023 rows=1 loops=1)
  Filter: (root AND ((name)::text ~~* '%die%'::text))
  Rows Removed by Filter: 49
Planning time: 0.136 ms
Execution time: 0.042 ms
  • 新的:
Sort  (cost=60.90..60.91 rows=2 width=14) (actual time=0.554..0.554 rows=2 loops=1)
  Sort Key: user_attributes.record_value
  Sort Method: quicksort  Memory: 25kB
  ->  Append  (cost=41.94..60.89 rows=2 width=14) (actual time=0.244..0.539 rows=2 loops=1)
        ->  Unique  (cost=41.94..41.95 rows=1 width=14) (actual time=0.243..0.243 rows=1 loops=1)
              ->  Sort  (cost=41.94..41.95 rows=1 width=14) (actual time=0.242..0.242 rows=1 loops=1)
                    Sort Key: user_attributes.record_value
                    Sort Method: quicksort  Memory: 25kB
                    ->  Nested Loop  (cost=26.42..41.93 rows=1 width=14) (actual time=0.224..0.231 rows=1 loops=1)
                          ->  Hash Semi Join  (cost=26.27..36.25 rows=5 width=22) (actual time=0.153..0.210 rows=2 loops=1)
                                Hash Cond: (user_attributes.record_value = user_attributes_1.record_value)
                                ->  Seq Scan on user_attributes  (cost=0.00..9.79 rows=50 width=22) (actual time=0.015..0.054 rows=50 loops=1)
                                      Filter: ((record_name)::text = 'Name'::text)
                                      Rows Removed by Filter: 333
                                ->  Hash  (cost=26.26..26.26 rows=1 width=14) (actual time=0.118..0.118 rows=2 loops=1)
                                      Buckets: 1024  Batches: 1  Memory Usage: 9kB
                                      ->  Hash Join  (cost=16.27..26.26 rows=1 width=14) (actual time=0.048..0.112 rows=2 loops=1)
                                            Hash Cond: (user_attributes_1.user_id = group_enrollments_1.user_id)
                                            ->  Seq Scan on user_attributes user_attributes_1  (cost=0.00..9.79 rows=50 width=22) (actual time=0.004..0.067 rows=50 loops=1)
                                                  Filter: ((record_name)::text = 'Name'::text)
                                                  Rows Removed by Filter: 333
                                            ->  Hash  (cost=16.25..16.25 rows=2 width=8) (actual time=0.013..0.013 rows=2 loops=1)
                                                  Buckets: 1024  Batches: 1  Memory Usage: 9kB
                                                  ->  Seq Scan on group_enrollments group_enrollments_1  (cost=0.00..16.25 rows=2 width=8) (actual time=0.007..0.010 rows=2 loops=1)
                                                        Filter: ((group_name)::text = 'group_admin'::text)
                                                        Rows Removed by Filter: 3
                          ->  Index Only Scan using group_enrollment_user_id_group_name_uindex on group_enrollments  (cost=0.15..1.13 rows=1 width=8) (actual time=0.007..0.007 rows=0 loops=2)
                                Index Cond: ((user_id = user_attributes.user_id) AND (group_name = 'b-sanus'::text))
                                Heap Fetches: 1
        ->  Nested Loop  (cost=0.15..18.92 rows=1 width=14) (actual time=0.018..0.292 rows=1 loops=1)
              ->  Seq Scan on user_attributes user_attributes_2  (cost=0.00..10.75 rows=1 width=22) (actual time=0.011..0.282 rows=2 loops=1)
                    Filter: ((record_value ~~* '%die%'::text) AND ((record_name)::text = 'name'::text))
                    Rows Removed by Filter: 381
              ->  Index Only Scan using group_enrollment_user_id_group_name_uindex on group_enrollments group_enrollments_2  (cost=0.15..8.17 rows=1 width=8) (actual time=0.002..0.002 rows=0 loops=2)
                    Index Cond: ((user_id = user_attributes_2.user_id) AND (group_name = 'root'::text))
                    Heap Fetches: 1
Planning time: 0.647 ms
Execution time: 0.628 ms

0 个答案:

没有答案
相关问题