Thread: Performance problems with 9.2.15

Performance problems with 9.2.15

From
Johan Fredriksson
Date:
Hello!

I am just about to upgrade from PostgreSQL 8.4.20 to 9.2.15, but I'v run
into some huge performance issues. Both databases are configured the
same way (shared_buffers = 2GB, temp_buffers = 32MB). I have increased
work_mem on the 9.2 from 4MB to 64MB, but to no avail.

Now, the query on 8.4:
rt4=# EXPLAIN ANALYZE VERBOSE SELECT DISTINCT main.* FROM Users main
CROSS JOIN ACL ACL_3 JOIN Principals Principals_1  ON ( Principals_1.id
= main.id ) JOIN CachedGroupMembers CachedGroupMembers_2  ON
( CachedGroupMembers_2.MemberId = Principals_1.id ) JOIN
CachedGroupMembers CachedGroupMembers_4  ON
( CachedGroupMembers_4.MemberId = Principals_1.id )  WHERE
((ACL_3.ObjectType = 'RT::Queue') OR (ACL_3.ObjectType = 'RT::System'
AND ACL_3.ObjectId   = 1)) AND (ACL_3.PrincipalId =
CachedGroupMembers_4.GroupId) AND (ACL_3.PrincipalType = 'Group') AND
(ACL_3.RightName = 'OwnTicket' OR ACL_3.RightName = 'SuperUser') AND
(CachedGroupMembers_2.Disabled = '0') AND (CachedGroupMembers_2.GroupId
= '4') AND (CachedGroupMembers_4.Disabled = '0') AND
(Principals_1.Disabled = '0') AND (Principals_1.PrincipalType = 'User')
AND (Principals_1.id != '1')  ORDER BY main.Name ASC;

                                                                                          

QUERY
PLAN

                                                                                          


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------
 Unique  (cost=19822.31..19843.46 rows=235 width=1084) (actual
time=6684.054..7118.015 rows=571 loops=1)
   Output: main.id, main.name, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.emailenc
oding, main.webencoding, main.externalcontactinfoid,
main.contactinfosystem, main.externalauthid, main.authsystem,
main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, ma
in.address2, main.city, main.state, main.zip, main.country,
main.timezone, main.pgpkey, main.creator, main.created,
main.lastupdatedby, main.lastupdated
   ->  Sort  (cost=19822.31..19822.90 rows=235 width=1084) (actual
time=6684.052..7085.835 rows=33310 loops=1)
         Output: main.id, main.name, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.em
ailencoding, main.webencoding, main.externalcontactinfoid,
main.contactinfosystem, main.externalauthid, main.authsystem,
main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.addres
s1, main.address2, main.city, main.state, main.zip, main.country,
main.timezone, main.pgpkey, main.creator, main.created,
main.lastupdatedby, main.lastupdated
         Sort Key: main.name, main.id, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.
emailencoding, main.webencoding, main.externalcontactinfoid,
main.contactinfosystem, main.externalauthid, main.authsystem,
main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.addr
ess1, main.address2, main.city, main.state, main.zip, main.country,
main.timezone, main.pgpkey, main.creator, main.created,
main.lastupdatedby, main.lastupdated
         Sort Method:  external merge  Disk: 7408kB
         ->  Hash Join  (cost=19659.66..19813.05 rows=235 width=1084)
(actual time=3362.897..4080.600 rows=33310 loops=1)
               Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, m
ain.emailencoding, main.webencoding, main.externalcontactinfoid,
main.contactinfosystem, main.externalauthid, main.authsystem,
main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.
address1, main.address2, main.city, main.state, main.zip, main.country,
main.timezone, main.pgpkey, main.creator, main.created,
main.lastupdatedby, main.lastupdated
               Hash Cond: (acl_3.principalid =
cachedgroupmembers_4.groupid)
               ->  Bitmap Heap Scan on acl acl_3  (cost=30.04..145.27
rows=494 width=4) (actual time=0.339..1.790 rows=528 loops=1)
                     Output: acl_3.id, acl_3.principaltype,
acl_3.principalid, acl_3.rightname, acl_3.objecttype, acl_3.objectid,
acl_3.creator, acl_3.created, acl_3.lastupdatedby, acl_3.lastupdated
                     Recheck Cond: ((((rightname)::text =
'OwnTicket'::text) AND ((principaltype)::text = 'Group'::text)) OR
(((rightname)::text = 'SuperUser'::text) AND ((principaltype)::text =
'Group'::text)))
                     Filter: (((objecttype)::text = 'RT::Queue'::text)
OR (((objecttype)::text = 'RT::System'::text) AND (objectid = 1)))
                     ->  BitmapOr  (cost=30.04..30.04 rows=529 width=0)
(actual time=0.303..0.303 rows=0 loops=1)
                           ->  Bitmap Index Scan on acl1
(cost=0.00..25.43 rows=518 width=0) (actual time=0.283..0.283 rows=524
loops=1)
                                 Index Cond: (((rightname)::text =
'OwnTicket'::text) AND ((principaltype)::text = 'Group'::text))
                           ->  Bitmap Index Scan on acl1
(cost=0.00..4.36 rows=11 width=0) (actual time=0.020..0.020 rows=4
loops=1)
                                 Index Cond: (((rightname)::text =
'SuperUser'::text) AND ((principaltype)::text = 'Group'::text))
               ->  Hash  (cost=19615.48..19615.48 rows=1131 width=1088)
(actual time=3301.001..3301.001 rows=949843 loops=1)
                     Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.l
ang, main.emailencoding, main.webencoding, main.externalcontactinfoid,
main.contactinfosystem, main.externalauthid, main.authsystem,
main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone,
 main.address1, main.address2, main.city, main.state, main.zip,
main.country, main.timezone, main.pgpkey, main.creator, main.created,
main.lastupdatedby, main.lastupdated, cachedgroupmembers_4.groupid
                     ->  Nested Loop  (cost=24.59..19615.48 rows=1131
width=1088) (actual time=0.540..1835.831 rows=949843 loops=1)
                           Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname,
main.lang, main.emailencoding, main.webencoding,
main.externalcontactinfoid, main.contactinfosystem, main.externalauthid,
main.authsystem, main.gecos, main.homephone, main.workphone,
main.mobilephone, main.pager
phone, main.address1, main.address2, main.city, main.state, main.zip,
main.country, main.timezone, main.pgpkey, main.creator, main.created,
main.lastupdatedby, main.lastupdated, cachedgroupmembers_4.groupid
                           ->  Nested Loop  (cost=18.63..8795.62 rows=41
width=1092) (actual time=0.438..22.198 rows=674 loops=1)
                                 Output: main.id, main.name,
main.password, main.authtoken, main.comments, main.signature,
main.emailaddress, main.freeformcontactinfo, main.organization,
main.realname, main.nick
name, main.lang, main.emailencoding, main.webencoding,
main.externalcontactinfoid, main.contactinfosystem, main.externalauthid,
main.authsystem, main.gecos, main.homephone, main.workphone,
main.mobilephone, main
.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.pgpkey, main.creator,
main.created, main.lastupdatedby, main.lastupdated,
cachedgroupmembers_2.member
id, principals_1.id
                                 ->  Nested Loop  (cost=18.63..8459.04
rows=41 width=8) (actual time=0.381..13.384 rows=674 loops=1)
                                       Output: principals_1.id,
cachedgroupmembers_2.memberid
                                       ->  Bitmap Heap Scan on
cachedgroupmembers cachedgroupmembers_2  (cost=18.63..2436.95 rows=669
width=4) (actual time=0.308..1.973 rows=675 loops=1)
                                             Output:
cachedgroupmembers_2.id, cachedgroupmembers_2.groupid,
cachedgroupmembers_2.memberid, cachedgroupmembers_2.via,
cachedgroupmembers_2.immediateparentid, cached
groupmembers_2.disabled
                                             Recheck Cond: (groupid = 4)
                                             Filter: (disabled = 0)
                                             ->  Bitmap Index Scan on
cachedgroupmembers3  (cost=0.00..18.46 rows=669 width=0) (actual
time=0.223..0.223 rows=675 loops=1)
                                                   Index Cond: (groupid
= 4)
                                       ->  Index Scan using
principals_pkey on principals principals_1  (cost=0.00..8.99 rows=1
width=4) (actual time=0.015..0.016 rows=1 loops=675)
                                             Output: principals_1.id,
principals_1.principaltype, principals_1.objectid, principals_1.disabled
                                             Index Cond:
(principals_1.id = cachedgroupmembers_2.memberid)
                                             Filter: ((principals_1.id
<> 1) AND (principals_1.disabled = 0) AND
((principals_1.principaltype)::text = 'User'::text))
                                 ->  Index Scan using users_pkey on
users main  (cost=0.00..8.20 rows=1 width=1084) (actual
time=0.010..0.011 rows=1 loops=674)
                                       Output: main.id, main.name,
main.password, main.authtoken, main.comments, main.signature,
main.emailaddress, main.freeformcontactinfo, main.organization,
main.realname, mai
n.nickname, main.lang, main.emailencoding, main.webencoding,
main.externalcontactinfoid, main.contactinfosystem, main.externalauthid,
main.authsystem, main.gecos, main.homephone, main.workphone,
main.mobilephone
, main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.pgpkey, main.creator,
main.created, main.lastupdatedby, main.lastupdated
                                       Index Cond: (main.id =
principals_1.id)
                           ->  Bitmap Heap Scan on cachedgroupmembers
cachedgroupmembers_4  (cost=5.96..263.05 rows=68 width=8) (actual
time=0.464..2.233 rows=1409 loops=674)
                                 Output: cachedgroupmembers_4.id,
cachedgroupmembers_4.groupid, cachedgroupmembers_4.memberid,
cachedgroupmembers_4.via, cachedgroupmembers_4.immediateparentid,
cachedgroupmembers
_4.disabled
                                 Recheck Cond:
(cachedgroupmembers_4.memberid = main.id)
                                 Filter: (cachedgroupmembers_4.disabled
= 0)
                                 ->  Bitmap Index Scan on
cachedgroupmembers2  (cost=0.00..5.95 rows=68 width=0) (actual
time=0.286..0.286 rows=1410 loops=674)
                                       Index Cond:
(cachedgroupmembers_4.memberid = main.id)
 Total runtime: 7120.012 ms

Same query on 9.2:
                                                   QUERY
PLAN
                                  


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
 Unique  (cost=8922.03..8922.11 rows=1 width=348) (actual
time=259143.677..259180.526 rows=572 loops=1)
   Output: main.id, main.name, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.gecos, m
ain.homephone, main.workphone, main.mobilephone, main.pagerphone,
main.address1, main.address2, main.city, main.state, main.zip,
main.country, main.timezone, main.creator, main.created,
main.lastupdatedby, main.
lastupdated, main.smimecertificate
   ->  Sort  (cost=8922.03..8922.04 rows=1 width=348) (actual
time=259143.674..259145.919 rows=33209 loops=1)
         Output: main.id, main.name, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.ge
cos, main.homephone, main.workphone, main.mobilephone, main.pagerphone,
main.address1, main.address2, main.city, main.state, main.zip,
main.country, main.timezone, main.creator, main.created,
main.lastupdatedby,
 main.lastupdated, main.smimecertificate
         Sort Key: main.name, main.id, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.
gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created,
main.lastupdatedb
y, main.lastupdated, main.smimecertificate
         Sort Method: quicksort  Memory: 13143kB
         ->  Nested Loop  (cost=47.83..8922.02 rows=1 width=348) (actual
time=388.225..258422.830 rows=33209 loops=1)
               Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, m
ain.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created,
main.lastupda
tedby, main.lastupdated, main.smimecertificate
               Join Filter: (cachedgroupmembers_4.groupid =
acl_3.principalid)
               Rows Removed by Join Filter: 495425041
               ->  Bitmap Heap Scan on public.acl acl_3
(cost=30.07..144.35 rows=497 width=4) (actual time=0.305..9.489 rows=525
loops=1)
                     Output: acl_3.id, acl_3.principaltype,
acl_3.principalid, acl_3.rightname, acl_3.objecttype, acl_3.objectid,
acl_3.creator, acl_3.created, acl_3.lastupdatedby, acl_3.lastupdated
                     Recheck Cond: ((((acl_3.rightname)::text =
'OwnTicket'::text) AND ((acl_3.principaltype)::text = 'Group'::text)) OR
(((acl_3.rightname)::text = 'SuperUser'::text) AND
((acl_3.principaltype):
:text = 'Group'::text)))
                     Filter: (((acl_3.objecttype)::text =
'RT::Queue'::text) OR (((acl_3.objecttype)::text = 'RT::System'::text)
AND (acl_3.objectid = 1)))
                     ->  BitmapOr  (cost=30.07..30.07 rows=531 width=0)
(actual time=0.270..0.270 rows=0 loops=1)
                           ->  Bitmap Index Scan on acl1
(cost=0.00..25.46 rows=521 width=0) (actual time=0.248..0.248 rows=521
loops=1)
                                 Index Cond: (((acl_3.rightname)::text =
'OwnTicket'::text) AND ((acl_3.principaltype)::text = 'Group'::text))
                           ->  Bitmap Index Scan on acl1
(cost=0.00..4.36 rows=11 width=0) (actual time=0.020..0.020 rows=4
loops=1)
                                 Index Cond: (((acl_3.rightname)::text =
'SuperUser'::text) AND ((acl_3.principaltype)::text = 'Group'::text))
               ->  Materialize  (cost=17.76..8740.41 rows=5 width=352)
(actual time=0.004..179.471 rows=943730 loops=525)
                     Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.l
ang, main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created,
main.la
stupdatedby, main.lastupdated, main.smimecertificate,
cachedgroupmembers_4.groupid
                     ->  Nested Loop  (cost=17.76..8740.38 rows=5
width=352) (actual time=0.436..1595.962 rows=943730 loops=1)
                           Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname,
main.lang, main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created, m
ain.lastupdatedby, main.lastupdated, main.smimecertificate,
cachedgroupmembers_4.groupid
                           ->  Nested Loop  (cost=14.17..8325.31 rows=3
width=356) (actual time=0.392..27.201 rows=675 loops=1)
                                 Output: main.id, main.name,
main.password, main.authtoken, main.comments, main.signature,
main.emailaddress, main.freeformcontactinfo, main.organization,
main.realname, main.nick
name, main.lang, main.gecos, main.homephone, main.workphone,
main.mobilephone, main.pagerphone, main.address1, main.address2,
main.city, main.state, main.zip, main.country, main.timezone,
main.creator, main.crea
ted, main.lastupdatedby, main.lastupdated, main.smimecertificate,
principals_1.id, cachedgroupmembers_2.memberid
                                 ->  Nested Loop  (cost=14.17..8160.17
rows=43 width=8) (actual time=0.351..16.568 rows=675 loops=1)
                                       Output: principals_1.id,
cachedgroupmembers_2.memberid
                                       ->  Bitmap Heap Scan on
public.cachedgroupmembers cachedgroupmembers_2  (cost=14.17..2431.45
rows=669 width=4) (actual time=0.303..2.098 rows=676 loops=1)
                                             Output:
cachedgroupmembers_2.id, cachedgroupmembers_2.groupid,
cachedgroupmembers_2.memberid, cachedgroupmembers_2.via,
cachedgroupmembers_2.immediateparentid, cached
groupmembers_2.disabled
                                             Recheck Cond:
(cachedgroupmembers_2.groupid = 4)
                                             Filter:
(cachedgroupmembers_2.disabled = 0)
                                             ->  Bitmap Index Scan on
cachedgroupmembers2  (cost=0.00..14.00 rows=669 width=0) (actual
time=0.215..0.215 rows=676 loops=1)
                                                   Index Cond:
(cachedgroupmembers_2.groupid = 4)
                                       ->  Index Scan using
principals_pkey on public.principals principals_1  (cost=0.00..8.55
rows=1 width=4) (actual time=0.019..0.020 rows=1 loops=676)
                                             Output: principals_1.id
                                             Index Cond:
(principals_1.id = cachedgroupmembers_2.memberid)
                                             Filter: ((principals_1.id
<> 1) AND (principals_1.disabled = 0) AND
((principals_1.principaltype)::text = 'User'::text))
                                             Rows Removed by Filter: 0
                                 ->  Index Scan using users_pkey on
public.users main  (cost=0.00..3.83 rows=1 width=348) (actual
time=0.014..0.015 rows=1 loops=675)
                                       Output: main.id, main.name,
main.password, main.authtoken, main.comments, main.signature,
main.emailaddress, main.freeformcontactinfo, main.organization,
main.realname, mai
n.nickname, main.lang, main.gecos, main.homephone, main.workphone,
main.mobilephone, main.pagerphone, main.address1, main.address2,
main.city, main.state, main.zip, main.country, main.timezone,
main.creator, mai
n.created, main.lastupdatedby, main.lastupdated, main.smimecertificate
                                       Index Cond: (main.id =
principals_1.id)
                           ->  Bitmap Heap Scan on
public.cachedgroupmembers cachedgroupmembers_4  (cost=3.59..137.70
rows=66 width=8) (actual time=0.340..2.016 rows=1398 loops=675)
                                 Output: cachedgroupmembers_4.id,
cachedgroupmembers_4.groupid, cachedgroupmembers_4.memberid,
cachedgroupmembers_4.via, cachedgroupmembers_4.immediateparentid,
cachedgroupmembers
_4.disabled
                                 Recheck Cond:
(cachedgroupmembers_4.memberid = principals_1.id)
                                 Filter: (cachedgroupmembers_4.disabled
= 0)
                                 Rows Removed by Filter: 0
                                 ->  Bitmap Index Scan on
cachedgroupmembers1  (cost=0.00..3.58 rows=66 width=0) (actual
time=0.210..0.210 rows=1398 loops=675)
                                       Index Cond:
(cachedgroupmembers_4.memberid = principals_1.id)
 Total runtime: 259230.400 ms


The 9.2 chose "nesed loop" in stead of "hash join" with a massive
penalty of 250 seconds in stead of 7-8 seconds.

I have tried to set "enable_nestloop = off" and then this query is down
to 4-5 seconds, but all other queries are slower.

How can I make PostgreSQL 9.2 run this query just as fast as 8.4 did?


          / Eskil



Re: Performance problems with 9.2.15

From
Tom Lane
Date:
Johan Fredriksson <eskil@kth.se> writes:
> I am just about to upgrade from PostgreSQL 8.4.20 to 9.2.15, but I'v run
> into some huge performance issues.

The rowcount estimates from 9.2 seem greatly different from the 8.4 plan.
Did you remember to ANALYZE all the tables after migrating?  Maybe there
were some table-specific statistics targets that you forgot to transfer
over?  In any case, the 9.2 plan looks like garbage-in-garbage-out to
me :-( ... without estimates at least a little closer to reality, the
planner is unlikely to do anything very sane.

(BTW, I wonder why you are moving only to 9.2 and not something more
recent.)

            regards, tom lane


Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
> The rowcount estimates from 9.2 seem greatly different from the 8.4 plan.
> Did you remember to ANALYZE all the tables after migrating?   Maybe there
> were some table-specific statistics targets that you forgot to transfer
> over?

No, I did not. Honestly I though everything would be transfered with a
dump/restore procedure. Unfortunatly running ANALYZE VERBOSE on all
involved tables did not really improve anything.

 > In any case, the 9.2 plan looks like garbage-in-garbage-out to
> me :-( ... without estimates at least a little closer to reality, the
> planner is unlikely to do anything very sane.
>
> (BTW, I wonder why you are moving only to 9.2 and not something more
> recent.)

Well, 9.2.15 is what comes bundled with RHEL 7, so I decided to go with
that to avoid dependency issues. But I could install a more fresh
version from scratch if that would solve my problem.


         / Eskil



Re: Performance problems with 9.2.15

From
Steve Crawford
Date:
...(BTW, I wonder why you are moving only to 9.2 and not something more
recent.)

Well, 9.2.15 is what comes bundled with RHEL 7, so I decided to go with that to avoid dependency issues. But I could install a more fresh version from scratch if that would solve my problem.

Generally my first step is to get the latest stable directly from the PostgreSQL Development Group, i.e.:

Then I know I'm starting with the latest and greatest and will get critical updates without worrying about any distribution packager delays.

Cheers,
Steve

Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
> > I am just about to upgrade from PostgreSQL 8.4.20 to 9.2.15, but I'v run
> > into some huge performance issues.
>
> The rowcount estimates from 9.2 seem greatly different from the 8.4 plan.
> Did you remember to ANALYZE all the tables after migrating?  Maybe there
> were some table-specific statistics targets that you forgot to transfer
> over?  In any case, the 9.2 plan looks like garbage-in-garbage-out to
> me :-( ... without estimates at least a little closer to reality, the
> planner is unlikely to do anything very sane.
>
> (BTW, I wonder why you are moving only to 9.2 and not something more
> recent.)

You put me on the right track with your conclusion that the estimates
were off the chart. The quick-and-dirty fix "DELETE FROM pg_statistic;"
solved this problem. This database now have to build up sane estimates
from scratch.


        / Eskil




Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
> > The rowcount estimates from 9.2 seem greatly different from the 8.4 plan.
> > Did you remember to ANALYZE all the tables after migrating?  Maybe there
> > were some table-specific statistics targets that you forgot to transfer
> > over?  In any case, the 9.2 plan looks like garbage-in-garbage-out to
> > me :-( ... without estimates at least a little closer to reality, the
> > planner is unlikely to do anything very sane.
> >
> > (BTW, I wonder why you are moving only to 9.2 and not something more
> > recent.)
>
> You put me on the right track with your conclusion that the estimates
> were off the chart. The quick-and-dirty fix "DELETE FROM pg_statistic;"
> solved this problem. This database now have to build up sane estimates
> from scratch.

Actually it took a VACUUM FULL; and DELETE FROM pg_statistic; followed
by ANALYZE on all tables to get it right.

Can someone please explain to me the difference between these two query
plans:

The bad one:
 Unique  (cost=6037.10..6037.18 rows=1 width=434) (actual
time=255608.588..255646.828 rows=572 loops=1)
   ->  Sort  (cost=6037.10..6037.11 rows=1 width=434) (actual
time=255608.583..255611.632 rows=33209 loops=1)
         Sort Method: quicksort  Memory: 13143kB
         ->  Nested Loop  (cost=42.51..6037.09 rows=1 width=434) (actual
time=152.818..254886.674 rows=33209 loops=1)
               Join Filter: (cachedgroupmembers_4.groupid =
acl_3.principalid)
               Rows Removed by Join Filter: 495425041
               ->  Bitmap Heap Scan on public.acl acl_3
(cost=30.07..144.35 rows=497 width=4) (actual time=0.284..8.184 rows=525
loops=1)
                     Recheck Cond: ((((acl_3.rightname)::text =
'OwnTicket'::text) AND ((acl_3.principaltype)::text = 'Group'::text)) OR
(((acl_3.rightname)::text = 'SuperUser'::text) AND
((acl_3.principaltype):
:text = 'Group'::text)))
                     Filter: (((acl_3.objecttype)::text =
'RT::Queue'::text) OR (((acl_3.objecttype)::text = 'RT::System'::text)
AND (acl_3.objectid = 1)))
                     ->  BitmapOr  (cost=30.07..30.07 rows=531 width=0)
(actual time=0.249..0.249 rows=0 loops=1)
                           ->  Bitmap Index Scan on acl1
(cost=0.00..25.46 rows=521 width=0) (actual time=0.233..0.233 rows=521
loops=1)
                                 Index Cond: (((acl_3.rightname)::text =
'OwnTicket'::text) AND ((acl_3.principaltype)::text = 'Group'::text))
                           ->  Bitmap Index Scan on acl1
(cost=0.00..4.36 rows=11 width=0) (actual time=0.016..0.016 rows=4
loops=1)
                                 Index Cond: (((acl_3.rightname)::text =
'SuperUser'::text) AND ((acl_3.principaltype)::text = 'Group'::text))
               ->  Materialize  (cost=12.44..5870.39 rows=3 width=438)
(actual time=0.004..176.296 rows=943730 loops=525)
                     ->  Nested Loop  (cost=12.44..5870.37 rows=3
width=438) (actual time=0.351..1028.683 rows=943730 loops=1)
                           ->  Nested Loop  (cost=12.44..5601.49 rows=2
width=442) (actual time=0.326..15.591 rows=675 loops=1)
                                 ->  Nested Loop  (cost=12.44..5502.26
rows=27 width=8) (actual time=0.303..9.744 rows=675 loops=1)
                                       Output: principals_1.id,
cachedgroupmembers_2.memberid
                                       ->  Bitmap Heap Scan on
public.cachedgroupmembers cachedgroupmembers_2  (cost=12.44..1659.12
rows=446 width=4) (actual time=0.267..1.266 rows=676 loops=1)

Recheck Cond: (cachedgroupmembers_2.groupid = 4)
                                             Filter:
(cachedgroupmembers_2.disabled = 0)
                                             ->  Bitmap Index Scan on
cachedgroupmembers2  (cost=0.00..12.33 rows=446 width=0) (actual
time=0.171..0.171 rows=676 loops=1)
                                                   Index Cond:
(cachedgroupmembers_2.groupid = 4)
                                       ->  Index Scan using
principals_pkey on public.principals principals_1  (cost=0.00..8.61
rows=1 width=4) (actual time=0.011..0.011 rows=1 loops=676)
                                             Output: principals_1.id
                                             Index Cond:
(principals_1.id = cachedgroupmembers_2.memberid)
                                             Filter: ((principals_1.id
<> 1) AND (principals_1.disabled = 0) AND
((principals_1.principaltype)::text = 'User'::text))
                                             Rows Removed by Filter: 0
                                 ->  Index Scan using users_pkey on
public.users main  (cost=0.00..3.67 rows=1 width=434) (actual
time=0.007..0.008 rows=1
loops=675)
                                       Index Cond: (main.id =
principals_1.id)
                           ->  Index Scan using cachedgroupmembers1 on
public.cachedgroupmembers cachedgroupmembers_4  (cost=0.00..133.79
rows=65 width=8) (actual time=0.012..1.199 rows=1398 loops=675)

                                 Index Cond:
(cachedgroupmembers_4.memberid = principals_1.id)
                                 Filter: (cachedgroupmembers_4.disabled
= 0)
                                 Rows Removed by Filter: 0
 Total runtime: 255694.440 ms
(47 rows)


The good one:
 Unique  (cost=528.88..528.96 rows=1 width=522) (actual
time=5029.906..5068.395 rows=572 loops=1)
   ->  Sort  (cost=528.88..528.89 rows=1 width=522) (actual
time=5029.889..5032.743 rows=33209 loops=1)
         Sort Method: quicksort  Memory: 13143kB
         ->  Nested Loop  (cost=36.08..528.87 rows=1 width=522) (actual
time=0.410..4178.931 rows=33209 loops=1)
               ->  Nested Loop  (cost=3.54..449.25 rows=2 width=526)
(actual time=0.139..1459.785 rows=943730 loops=1)
                     Join Filter: (principals_1.id =
cachedgroupmembers_4.memberid)
                     ->  Nested Loop  (cost=0.00..314.65 rows=1
width=530) (actual time=0.115..12.537 rows=675 loops=1)
                           ->  Nested Loop  (cost=0.00..310.98 rows=1
width=8) (actual time=0.106..7.203 rows=675 loops=1)
                                 Output: principals_1.id,
cachedgroupmembers_2.memberid
                                 ->  Index Only Scan using disgroumem on
public.cachedgroupmembers cachedgroupmembers_2  (cost=0.00..101.59
rows=24 width=4) (actual time=0.071..1.046 rows=676 loops=1)
                                       Output:
cachedgroupmembers_2.groupid, cachedgroupmembers_2.memberid,
cachedgroupmembers_2.disabled
                                       Index Cond:
((cachedgroupmembers_2.groupid = 4) AND (cachedgroupmembers_2.disabled =
0))
                                       Heap Fetches: 676
                                 ->  Index Scan using principals_pkey on
public.principals principals_1  (cost=0.00..8.71 rows=1 width=4) (actual
time=0.008..0.008 rows=1 loops=676)
                                       Output: principals_1.id
                                       Index Cond: (principals_1.id =
cachedgroupmembers_2.memberid)
                                       Filter: ((principals_1.id <> 1)
AND (principals_1.disabled = 0) AND ((principals_1.principaltype)::text
= 'User'::text))
                                       Rows Removed by Filter: 0
                           ->  Index Scan using users_pkey on
public.users main  (cost=0.00..3.67 rows=1 width=522) (actual
time=0.006..0.007 rows=1 loops=675)
                                 Index Cond: (main.id = principals_1.id)
                     ->  Bitmap Heap Scan on public.cachedgroupmembers
cachedgroupmembers_4  (cost=3.54..133.77 rows=66 width=8) (actual
time=0.309..1.752 rows=1398 loops=675)
                           Recheck Cond: (cachedgroupmembers_4.memberid
= main.id)
                           Filter: (cachedgroupmembers_4.disabled = 0)
                           Rows Removed by Filter: 0
                           ->  Bitmap Index Scan on cachedgroupmembers1
(cost=0.00..3.52 rows=66 width=0) (actual time=0.185..0.185 rows=1398
loops=675)
                                 Index Cond:
(cachedgroupmembers_4.memberid = main.id)
               ->  Bitmap Heap Scan on public.acl acl_3
(cost=32.54..39.78 rows=3 width=4) (actual time=0.002..0.002 rows=0
loops=943730)
                     Recheck Cond: ((acl_3.principalid =
cachedgroupmembers_4.groupid) AND ((((acl_3.rightname)::text =
'OwnTicket'::text) AND ((acl_3.principaltype)::text = 'Group'::text)) OR
(((acl_3.rightname
)::text = 'SuperUser'::text) AND ((acl_3.principaltype)::text =
'Group'::text))))
                     Filter: (((acl_3.objecttype)::text =
'RT::Queue'::text) OR (((acl_3.objecttype)::text = 'RT::System'::text)
AND (acl_3.objectid = 1)))
                     ->  BitmapAnd  (cost=32.54..32.54 rows=3 width=0)
(actual time=0.002..0.002 rows=0 loops=943730)
                           ->  Bitmap Index Scan on acl3
(cost=0.00..2.22 rows=49 width=0) (actual time=0.001..0.001 rows=1
loops=943730)
                                 Index Cond: (acl_3.principalid =
cachedgroupmembers_4.groupid)
                           ->  BitmapOr  (cost=30.07..30.07 rows=531
width=0) (actual time=0.110..0.110 rows=0 loops=4412)
                                 ->  Bitmap Index Scan on acl1
(cost=0.00..25.46 rows=521 width=0) (actual time=0.102..0.102 rows=521
loops=4412)
                                       Index Cond:
(((acl_3.rightname)::text = 'OwnTicket'::text) AND
((acl_3.principaltype)::text = 'Group'::text))
                                 ->  Bitmap Index Scan on acl1
(cost=0.00..4.36 rows=11 width=0) (actual time=0.007..0.007 rows=4
loops=4412)
                                       Index Cond:
(((acl_3.rightname)::text = 'SuperUser'::text) AND
((acl_3.principaltype)::text = 'Group'::text))
 Total runtime: 5069.842 ms
(47 rows)


Why does PostgreSQL pick one before the other and how can I make sure
that it will keep using the "good" one instead of the "bad" one?

        / Eskil




Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
> > > The rowcount estimates from 9.2 seem greatly different from the 8.4 plan.
> > > Did you remember to ANALYZE all the tables after migrating?  Maybe there
> > > were some table-specific statistics targets that you forgot to transfer
> > > over?  In any case, the 9.2 plan looks like garbage-in-garbage-out to
> > > me :-( ... without estimates at least a little closer to reality, the
> > > planner is unlikely to do anything very sane.
> > >
> > > (BTW, I wonder why you are moving only to 9.2 and not something more
> > > recent.)
> >
> > You put me on the right track with your conclusion that the estimates
> > were off the chart. The quick-and-dirty fix "DELETE FROM pg_statistic;"
> > solved this problem. This database now have to build up sane estimates
> > from scratch.
>
> Actually it took a VACUUM FULL; and DELETE FROM pg_statistic; followed
> by ANALYZE on all tables to get it right.

It worked last time, but this time it does not work. I have deleted all
data in the table pg_statistic and run ANALYZE on all tables but the
planner still make crappy optimizations. How can I adjust the estimates
to make the planner work better?

Last time it was in testing, this time it is in production, so urgent
help is needed, please!

This query now takes 90 seconds and it should not take more than 4-5
seconds.

EXPLAIN ANALYZE VERBOSE SELECT DISTINCT main.* FROM Users main CROSS
JOIN ACL ACL_3 JOIN Principals Principals_1  ON ( Principals_1.id =
main.id ) JOIN CachedGroupMembers CachedGroupMembers_2  ON
( CachedGroupMembers_2.MemberId = Principals_1.id ) JOIN
CachedGroupMembers CachedGroupMembers_4  ON
( CachedGroupMembers_4.MemberId = Principals_1.id )  WHERE
((ACL_3.ObjectType = 'RT::Queue' AND ACL_3.ObjectId   = 85) OR
(ACL_3.ObjectType = 'RT::System' AND ACL_3.ObjectId   = 1)) AND
(ACL_3.PrincipalId = CachedGroupMembers_4.GroupId) AND
(ACL_3.PrincipalType = 'Group') AND (ACL_3.RightName = 'OwnTicket') AND
(CachedGroupMembers_2.Disabled = '0') AND (CachedGroupMembers_2.GroupId
= '4') AND (CachedGroupMembers_4.Disabled = '0') AND
(Principals_1.Disabled = '0') AND (Principals_1.PrincipalType = 'User')
AND (Principals_1.id != '1')  ORDER BY main.Name ASC;

                                                                                           
                                                QUERY
PLAN
                                     


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------
 Unique  (cost=8907.68..8907.76 rows=1 width=336) (actual
time=92075.721..92076.336 rows=176 loops=1)
   Output: main.id, main.name, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.gecos, m
ain.homephone, main.workphone, main.mobilephone, main.pagerphone,
main.address1, main.address2, main.city, main.state, main.zip,
main.country, main.timezone, main.creator, main.created,
main.lastupdatedby, main.
lastupdated, main.smimecertificate
   ->  Sort  (cost=8907.68..8907.69 rows=1 width=336) (actual
time=92075.720..92075.748 rows=607 loops=1)
         Output: main.id, main.name, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.ge
cos, main.homephone, main.workphone, main.mobilephone, main.pagerphone,
main.address1, main.address2, main.city, main.state, main.zip,
main.country, main.timezone, main.creator, main.created,
main.lastupdatedby,
 main.lastupdated, main.smimecertificate
         Sort Key: main.name, main.id, main.password, main.authtoken,
main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, main.
gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created,
main.lastupdatedb
y, main.lastupdated, main.smimecertificate
         Sort Method: quicksort  Memory: 243kB
         ->  Nested Loop  (cost=20.37..8907.67 rows=1 width=336) (actual
time=540.971..92062.584 rows=607 loops=1)
               Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.lang, m
ain.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created,
main.lastupda
tedby, main.lastupdated, main.smimecertificate
               ->  Nested Loop  (cost=20.37..8845.47 rows=3 width=340)
(actual time=0.188..1204.040 rows=972439 loops=1)
                     Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname, main.l
ang, main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created,
main.la
stupdatedby, main.lastupdated, main.smimecertificate,
cachedgroupmembers_4.groupid
                     ->  Nested Loop  (cost=20.37..8568.24 rows=2
width=344) (actual time=0.179..11.075 rows=688 loops=1)
                           Output: main.id, main.name, main.password,
main.authtoken, main.comments, main.signature, main.emailaddress,
main.freeformcontactinfo, main.organization, main.realname,
main.nickname,
main.lang, main.gecos, main.homephone, main.workphone, main.mobilephone,
main.pagerphone, main.address1, main.address2, main.city, main.state,
main.zip, main.country, main.timezone, main.creator, main.created, m
ain.lastupdatedby, main.lastupdated, main.smimecertificate,
principals_1.id, cachedgroupmembers_2.memberid
                           ->  Nested Loop  (cost=20.37..8411.79 rows=41
width=8) (actual time=0.170..6.551 rows=688 loops=1)
                                 Output: principals_1.id,
cachedgroupmembers_2.memberid
                                 ->  Bitmap Heap Scan on
public.cachedgroupmembers cachedgroupmembers_2  (cost=20.37..2510.57
rows=689 width=4) (actual time=0.156..1.362 rows=689 loops=1)
                                       Output: cachedgroupmembers_2.id,
cachedgroupmembers_2.groupid, cachedgroupmembers_2.memberid,
cachedgroupmembers_2.via, cachedgroupmembers_2.immediateparentid,
cachedgroupm
embers_2.disabled
                                       Recheck Cond:
((cachedgroupmembers_2.groupid = 4) AND (cachedgroupmembers_2.disabled =
0))
                                       ->  Bitmap Index Scan on
disgroumem  (cost=0.00..20.20 rows=689 width=0) (actual
time=0.107..0.107 rows=689 loops=1)
                                             Index Cond:
((cachedgroupmembers_2.groupid = 4) AND (cachedgroupmembers_2.disabled =
0))
                                 ->  Index Scan using principals_pkey on
public.principals principals_1  (cost=0.00..8.55 rows=1 width=4) (actual
time=0.006..0.007 rows=1 loops=689)
                                       Output: principals_1.id
                                       Index Cond: (principals_1.id =
cachedgroupmembers_2.memberid)
                                       Filter: ((principals_1.id <> 1)
AND (principals_1.disabled = 0) AND ((principals_1.principaltype)::text
= 'User'::text))
                                       Rows Removed by Filter: 0
                           ->  Index Scan using users_pkey on
public.users main  (cost=0.00..3.81 rows=1 width=336) (actual
time=0.005..0.006 rows=1 loops=688)
                                 Output: main.id, main.name,
main.password, main.authtoken, main.comments, main.signature,
main.emailaddress, main.freeformcontactinfo, main.organization,
main.realname, main.nick
name, main.lang, main.gecos, main.homephone, main.workphone,
main.mobilephone, main.pagerphone, main.address1, main.address2,
main.city, main.state, main.zip, main.country, main.timezone,
main.creator, main.crea
ted, main.lastupdatedby, main.lastupdated, main.smimecertificate
                                 Index Cond: (main.id = principals_1.id)
                     ->  Index Scan using cachedgroupmembers1 on
public.cachedgroupmembers cachedgroupmembers_4  (cost=0.00..137.96
rows=65 width=8) (actual time=0.008..1.434 rows=1413 loops=688)
                           Output: cachedgroupmembers_4.id,
cachedgroupmembers_4.groupid, cachedgroupmembers_4.memberid,
cachedgroupmembers_4.via, cachedgroupmembers_4.immediateparentid,
cachedgroupmembers_4.dis
abled
                           Index Cond: (cachedgroupmembers_4.memberid =
principals_1.id)
                           Filter: (cachedgroupmembers_4.disabled = 0)
                           Rows Removed by Filter: 0
               ->  Index Only Scan using acl1 on public.acl acl_3
(cost=0.00..20.72 rows=1 width=4) (actual time=0.093..0.093 rows=0
loops=972439)
                     Output: acl_3.rightname, acl_3.objecttype,
acl_3.objectid, acl_3.principaltype, acl_3.principalid
                     Index Cond: ((acl_3.rightname = 'OwnTicket'::text)
AND (acl_3.principaltype = 'Group'::text) AND (acl_3.principalid =
cachedgroupmembers_4.groupid))
                     Filter: ((((acl_3.objecttype)::text =
'RT::Queue'::text) AND (acl_3.objectid = 85)) OR
(((acl_3.objecttype)::text = 'RT::System'::text) AND (acl_3.objectid =
1)))
                     Rows Removed by Filter: 0
                     Heap Fetches: 33532
 Total runtime: 92076.507 ms
(39 rows)



        / Eskil




Re: Performance problems with 9.2.15

From
Claudio Freire
Date:
On Thu, Jul 21, 2016 at 11:48 AM, Johan Fredriksson <eskil@kth.se> wrote:
> EXPLAIN ANALYZE VERBOSE SELECT DISTINCT main.* FROM Users main CROSS
> JOIN ACL ACL_3 JOIN Principals Principals_1  ON ( Principals_1.id =
> main.id ) JOIN CachedGroupMembers CachedGroupMembers_2  ON
> ( CachedGroupMembers_2.MemberId = Principals_1.id ) JOIN
> CachedGroupMembers CachedGroupMembers_4  ON
> ( CachedGroupMembers_4.MemberId = Principals_1.id )  WHERE
> ((ACL_3.ObjectType = 'RT::Queue' AND ACL_3.ObjectId   = 85) OR
> (ACL_3.ObjectType = 'RT::System' AND ACL_3.ObjectId   = 1)) AND
> (ACL_3.PrincipalId = CachedGroupMembers_4.GroupId) AND
> (ACL_3.PrincipalType = 'Group') AND (ACL_3.RightName = 'OwnTicket') AND
> (CachedGroupMembers_2.Disabled = '0') AND (CachedGroupMembers_2.GroupId
> = '4') AND (CachedGroupMembers_4.Disabled = '0') AND
> (Principals_1.Disabled = '0') AND (Principals_1.PrincipalType = 'User')
> AND (Principals_1.id != '1')  ORDER BY main.Name ASC;


That cross join doesn't look right. It has no join condition.


Re: Performance problems with 9.2.15

From
"David G. Johnston"
Date:
On Thu, Jul 21, 2016 at 2:24 PM, Claudio Freire <klaussfreire@gmail.com> wrote:
That cross join doesn't look right. It has no join condition.

​That is that the definition of a "CROSS JOIN"...

David J.

Re: Performance problems with 9.2.15

From
Claudio Freire
Date:
On Thu, Jul 21, 2016 at 3:29 PM, David G. Johnston
<david.g.johnston@gmail.com> wrote:
> On Thu, Jul 21, 2016 at 2:24 PM, Claudio Freire <klaussfreire@gmail.com>
> wrote:
>>
>> That cross join doesn't look right. It has no join condition.
>
>
> That is that the definition of a "CROSS JOIN"...
>
> David J.

Well, maybe it shouldn't be.

A cross join I mean.

I see the query and a cross join there doesn't make much sense.

There's no filtering of the output rows on the where clause either
AFAICT, and it's producing a lot of intermediate rows that don't seem
to be necessary. That was my point.


Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
I can add that setting enable_nestloop = 0 cuts the runtime for this query down to about 4 seconds.
Disabling nested loops globaly does however impacts performance of a lot of other queries.

        / Eskil

Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
And by the way, I have also tried to upgrade to Postgresql 9.4.8 (the latest version in postgresl.org's own repository)
withoutimprovment. 

        / Eskil

Re: Performance problems with 9.2.15

From
Mark Kirkwood
Date:
On 22/07/16 13:07, Johan Fredriksson wrote:
> And by the way, I have also tried to upgrade to Postgresql 9.4.8 (the latest version in postgresl.org's own
repository)without improvment. 
>

Not sure what repo you are using, but 9.5.3 and 9.6 Beta are the
*actual* latest versions. Now I'm not sure they will actually help your
particular query, but are probably worth a try out!

regards

Mark




Re: Performance problems with 9.2.15

From
Johan Fredriksson
Date:
fre 2016-07-22 klockan 19:08 +1200 skrev Mark Kirkwood:
> On 22/07/16 13:07, Johan Fredriksson wrote:
> > And by the way, I have also tried to upgrade to Postgresql 9.4.8 (the latest version in postgresl.org's own
repository)without improvment. 
> >
>
> Not sure what repo you are using, but 9.5.3 and 9.6 Beta are the
> *actual* latest versions. Now I'm not sure they will actually help your
> particular query, but are probably worth a try out!

The one I found on https://www.postgresql.org/download/linux/redhat/

That page points out
http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-redhat94-9.4-1.noarch.rpm as the latest. Perhaps the
download-pageneed to be updated? 


        / Eskil