BUG #2872: SELECT from view with OR fast in 8.1, slow in 8.2

Поиск
Список
Период
Сортировка
От Nicholas Vinen
Тема BUG #2872: SELECT from view with OR fast in 8.1, slow in 8.2
Дата
Msg-id 200701031803.l03I3eev021803@wwwmaster.postgresql.org
обсуждение исходный текст
Ответы Re: BUG #2872: SELECT from view with OR fast in 8.1, slow in 8.2  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-bugs
The following bug has been logged online:

Bug reference:      2872
Logged by:          Nicholas Vinen
Email address:      hb@pg.x256.org
PostgreSQL version: 8.2.0
Operating system:   Linux (AMD64)
Description:        SELECT from view with OR fast in 8.1, slow in 8.2
Details:

Sorry that I can't provide data, there's some private information in there,
but hopefully this will be easy enough to reproduce.

I have these tables and this view:


        View "public.users_groups"
       Column       |  Type   | Modifiers
--------------------+---------+-----------
 group_id           | integer |
 group_name         | text    |
 group_emailaddress | text    |
 group_disabled     | boolean |
 user_id            | integer |
 user_name          | text    |
 user_display_name  | text    |
 user_emailaddress  | text    |
 user_disabled      | boolean |
View definition:
 SELECT g.id AS group_id, g.name AS group_name, g.emailaddress AS
group_emailaddress, pg.disabled AS group_disabled, u.id AS user_id,
u.realname AS user_name, u.displayname AS user_display_name, u.emailaddress
AS user_emailaddress, pu.disabled AS user_disabled
   FROM groups g
   JOIN principals pg ON pg.objectid = g.id
   JOIN cachedgroupmembers cgm ON cgm.groupid = g.id AND NOT cgm.disabled
   JOIN users u ON u.id = cgm.memberid
   JOIN principals pu ON pu.objectid = u.id;

                                     Table "helpdesk_mirror.users"
        Column         |           Type           |
Modifiers
-----------------------+--------------------------+-------------------------
---------------------------
 id                    | integer                  | not null default
nextval('users_id_seq'::regclass)
 name                  | text                     | not null default
''::text
 password              | text                     |
 comments              | bytea                    |
 signature             | bytea                    |
 emailaddress          | text                     |
 freeformcontactinfo   | text                     |
 organization          | text                     |
 realname              | text                     |
 nickname              | text                     |
 lang                  | text                     |
 emailencoding         | text                     |
 webencoding           | text                     |
 externalcontactinfoid | text                     |
 contactinfosystem     | text                     |
 externalauthid        | text                     |
 authsystem            | text                     |
 gecos                 | text                     |
 homephone             | text                     |
 workphone             | text                     |
 mobilephone           | text                     |
 pagerphone            | text                     |
 address1              | text                     |
 address2              | text                     |
 city                  | text                     |
 state                 | text                     |
 zip                   | text                     |
 country               | text                     |
 timezone              | text                     |
 pgpkey                | text                     |
 creator               | integer                  | not null default 0
 created               | timestamp with time zone |
 lastupdatedby         | integer                  | not null default 0
 lastupdated           | timestamp with time zone |
 focus                 | text                     |
 focuscount            | integer                  |
 focusproblemcount     | integer                  |
 focusprojectcount     | integer                  |
 focusrequestcount     | integer                  |
 focussuggestioncount  | integer                  |
 focusfeedbackcount    | integer                  |
 portraitgeometry      | text                     |
 focusuntypedcount     | integer                  |
 lastloginip           | text                     |
 lastloginhostname     | text                     |
 defaultqueue          | integer                  |
 interface             | text                     |
 default_ownerassignee | text                     |
 flags                 | text                     |
 guid                  | bytea                    |
 displayname           | text                     |
 title                 | text                     |
 department            | text                     |
 emailalias            | text                     |
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
    "users_name_key" UNIQUE, btree (name)
    "users_emailaddress_idx" btree (emailaddress)
Triggers:
    users_trig_final AFTER INSERT OR DELETE OR UPDATE ON users FOR EACH ROW
EXECUTE PROCEDURE mirror_config.log_changes()

                        Table "helpdesk_mirror.groups"
    Column    |  Type   |                      Modifiers

--------------+---------+---------------------------------------------------
--
 id           | integer | not null default
nextval('groups_id_seq'::regclass)
 name         | text    |
 description  | text    |
 domain       | text    |
 type         | text    |
 instance     | integer |
 emailaddress | text    |
 guid         | bytea   |
Indexes:
    "groups_pkey" PRIMARY KEY, btree (id)
    "groups_domain_idx" btree ("domain")
    "groups_emailaddress_idx" btree (emailaddress)
    "groups_instance_idx" btree (instance)
    "groups_name_idx" btree (name)
    "groups_type_idx" btree ("type")
Triggers:
    groups_trig_final AFTER INSERT OR DELETE OR UPDATE ON groups FOR EACH
ROW EXECUTE PROCEDURE mirror_config.log_changes()

                        Table "helpdesk_mirror.principals"
    Column     |  Type   |                        Modifiers

---------------+---------+--------------------------------------------------
-------
 id            | integer | not null default
nextval('principals_id_seq'::regclass)
 principaltype | text    | not null default ''::text
 objectid      | integer |
 disabled      | boolean | not null default false
Indexes:
    "principals_pkey" PRIMARY KEY, btree (id)
    "principals_objectid_key" UNIQUE, btree (objectid)
    "principals_objectid_idx" btree (objectid)
    "principals_principaltype" btree (principaltype)
Triggers:
    principals_trig_final AFTER INSERT OR DELETE OR UPDATE ON principals FOR
EACH ROW EXECUTE PROCEDURE mirror_config.log_changes()

                      Table "helpdesk_mirror.cachedgroupmembers"
  Column  |  Type   |                            Modifiers

----------+---------+-------------------------------------------------------
----------
 id       | integer | not null default
nextval('cachedgroupmembers_id_seq'::regclass)
 groupid  | integer | not null default 0
 memberid | integer | not null default 0
 disabled | boolean | not null default false
Indexes:
    "cachedgroupmembers_pkey" PRIMARY KEY, btree (id)
    "cachedgroupmembers_groupidmemberid_idx" btree (groupid, memberid)
CLUSTER
    "cachedgroupmembers_memberid_idx" btree (memberid)
Triggers:
    cachedgroupmembers_trig_final AFTER INSERT OR DELETE OR UPDATE ON
cachedgroupmembers FOR EACH ROW EXECUTE PROCEDURE
mirror_config.log_changes()

Here is the problem:

rt3=# explain analyze SELECT * FROM users_groups WHERE user_id = '9752'
UNION SELECT * FROM users_groups WHERE group_id = '9752';

                    QUERY PLAN

----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------
 Unique  (cost=87.67..87.74 rows=3 width=143) (actual time=6.666..6.741
rows=18 loops=1)
   ->  Sort  (cost=87.67..87.67 rows=3 width=143) (actual time=6.663..6.685
rows=18 loops=1)
         Sort Key: group_id, group_name, group_emailaddress, group_disabled,
user_id, user_name, user_display_name, user_emailaddress, user_disabled
         ->  Append  (cost=0.00..87.64 rows=3 width=143) (actual
time=0.282..6.496 rows=18 loops=1)
               ->  Nested Loop  (cost=0.00..18.32 rows=2 width=143) (actual
time=0.045..0.045 rows=0 loops=1)
                     ->  Nested Loop  (cost=0.00..13.40 rows=2 width=94)
(actual time=0.043..0.043 rows=0 loops=1)
                           ->  Nested Loop  (cost=0.00..8.48 rows=2
width=89) (actual time=0.040..0.040 rows=0 loops=1)
                                 ->  Nested Loop  (cost=0.00..4.81 rows=1
width=85) (actual time=0.037..0.037 rows=0 loops=1)
                                       ->  Index Scan using users_pkey on
users u  (cost=0.00..2.35 rows=1 width=84) (actual time=0.035..0.035 rows=0
loops=1)
                                             Index Cond: (id = 9752)
                                       ->  Index Scan using
principals_objectid_key on principals pu  (cost=0.00..2.36 rows=1 width=5)
(never executed)
                                             Index Cond: (9752 = objectid)
                                 ->  Index Scan using
cachedgroupmembers_memberid_idx on cachedgroupmembers cgm  (cost=0.00..3.47
rows=2 width=8) (never executed)
                                       Index Cond: (9752 = memberid)
                                       Filter: (NOT disabled)
                           ->  Index Scan using principals_objectid_key on
principals pg  (cost=0.00..2.36 rows=1 width=5) (never executed)
                                 Index Cond: (cgm.groupid = pg.objectid)
                     ->  Index Scan using groups_pkey on groups g
(cost=0.00..2.36 rows=1 width=57) (never executed)
                           Index Cond: (pg.objectid = g.id)
               ->  Nested Loop  (cost=0.00..69.02 rows=1 width=143) (actual
time=0.233..6.406 rows=18 loops=1)
                     ->  Nested Loop  (cost=0.00..66.56 rows=1 width=142)
(actual time=0.203..6.186 rows=18 loops=1)
                           ->  Nested Loop  (cost=0.00..64.10 rows=1
width=89) (actual time=0.138..5.929 rows=18 loops=1)
                                 ->  Nested Loop  (cost=0.00..61.64 rows=1
width=92) (actual time=0.085..5.417 rows=18 loops=1)
                                       ->  Index Scan using
cachedgroupmembers_groupidmemberid_idx on cachedgroupmembers cgm
(cost=0.00..25.17 rows=23 width=8) (actual time=0.064..0.129 rows=20
loops=1)
                                             Index Cond: (9752 = groupid)
                                             Filter: (NOT disabled)
                                       ->  Index Scan using users_pkey on
users u  (cost=0.00..1.48 rows=1 width=84) (actual time=0.257..0.259 rows=1
loops=20)
                                             Index Cond: (u.id =
cgm.memberid)
                                 ->  Index Scan using
principals_objectid_key on principals pu  (cost=0.00..2.36 rows=1 width=5)
(actual time=0.022..0.023 rows=1 loops=18)
                                       Index Cond: (pu.objectid = u.id)
                           ->  Index Scan using groups_pkey on groups g
(cost=0.00..2.36 rows=1 width=57) (actual time=0.007..0.009 rows=1
loops=18)
                                 Index Cond: (id = 9752)
                     ->  Index Scan using principals_objectid_key on
principals pg  (cost=0.00..2.36 rows=1 width=5) (actual time=0.005..0.006
rows=1 loops=18)
                           Index Cond: (9752 = objectid)
 Total runtime: 7.112 ms
(35 rows)
rt3=# explain analyze SELECT * FROM users_groups WHERE (group_id = '9752' or
user_id = '9752');

        QUERY PLAN

----------------------------------------------------------------------------
----------------------------------------------------------------------------
-----------------------------
 Nested Loop  (cost=0.00..12442.41 rows=4 width=143) (actual
time=875.204..41218.950 rows=18 loops=1)
   ->  Nested Loop  (cost=0.00..12440.56 rows=4 width=146) (actual
time=875.165..41218.242 rows=18 loops=1)
         ->  Nested Loop  (cost=0.00..12437.27 rows=4 width=149) (actual
time=875.113..41207.734 rows=18 loops=1)
               Join Filter: ((g.id = 9752) OR (u.id = 9752))
               ->  Nested Loop  (cost=0.00..6528.63 rows=6503 width=92)
(actual time=0.094..16219.575 rows=312649 loops=1)
                     ->  Index Scan using users_pkey on users u
(cost=0.00..239.51 rows=1641 width=84) (actual time=0.042..100.580 rows=1642
loops=1)
                     ->  Index Scan using cachedgroupmembers_memberid_idx on
cachedgroupmembers cgm  (cost=0.00..3.42 rows=4 width=8) (actual
time=0.122..9.296 rows=190 loops=1642)
                           Index Cond: (u.id = cgm.memberid)
                           Filter: (NOT disabled)
               ->  Index Scan using groups_pkey on groups g
(cost=0.00..0.80 rows=1 width=57) (actual time=0.074..0.075 rows=1
loops=312649)
                     Index Cond: (cgm.groupid = g.id)
         ->  Index Scan using principals_objectid_key on principals pu
(cost=0.00..0.72 rows=1 width=5) (actual time=0.573..0.575 rows=1 loops=18)
               Index Cond: (pu.objectid = u.id)
   ->  Index Scan using principals_objectid_key on principals pg
(cost=0.00..0.36 rows=1 width=5) (actual time=0.030..0.032 rows=1 loops=18)
         Index Cond: (pg.objectid = g.id)
 Total runtime: 41219.442 ms
(16 rows)

This was never a problem with 8.1.x.



Nicholas

В списке pgsql-bugs по дате отправления:

Предыдущее
От: "Dan Horacek"
Дата:
Сообщение: BUG #2871: LDAP authentication problem
Следующее
От: "Vishwanath, Kiran - Mission"
Дата:
Сообщение: Installing PGSQL on Windows XP