Re: Help Me Understand Why I'm Getting a Bad Query Plan

From: Bryan Murphy <bmurphy1976(at)gmail(dot)com>
To: pgsql-performance(at)postgresql(dot)org
Subject: Re: Help Me Understand Why I'm Getting a Bad Query Plan
Date: 2009-03-24 22:21:52
Message-ID: 7fd310d10903241521v1cbf5d7aueca653e03ed98649@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-performance

I hate to nag, but could anybody help me with this? We have a few
related queries that are causing noticeable service delays in our
production system. I've tried a number of different things, but I'm
running out of ideas and don't know what to do next.

Thanks,
Bryan

On Mon, Mar 23, 2009 at 2:03 PM, Bryan Murphy <bmurphy1976(at)gmail(dot)com> wrote:
> Hey Guys,
>
> I've got a query on our production system that isn't choosing a good
> plan.  I can't see why it's choosing to do a sequential scan on the
> ItemExperienceLog table.  That table is about 800mb and has about 2.5
> million records.  This example query only returns 4 records.  I've
> tried upping the statics for ItemExperienceLog.VistorId and
> ItemExperienceLog.ItemId to 1000 (from out default of 100) with no
> success.
>
> Our primary keys are guids stored as char(32) not null.  Our database
> uses UTF-8 encoding and is currently version v8.3.5.
>
> The queries:
>
>
>
> --SET enable_seqscan = off
> --SET enable_seqscan = on
>
> --ALTER TABLE ItemExperienceLog ALTER COLUMN VisitorId SET STATISTICS 1000
> --ALTER TABLE ItemExperienceLog ALTER COLUMN ItemId SET STATISTICS 1000
> --ANALYZE ItemExperienceLog
>
> SELECT MAX(l.Id) as Id, l.ItemId
> FROM ItemExperienceLog l
> INNER JOIN Items_Primary p ON p.Id = l.ItemId
> INNER JOIN Feeds f ON f.Id = p.FeedId
> INNER JOIN Visitors v ON v.Id = l.VisitorId
> WHERE
>        v.UserId = 'fbe2537f21d94f519605612c0bf7c2c5'
>        AND LOWER(f.Slug) = LOWER('Wealth_Building_by_NightingaleConant')
> GROUP BY l.ItemId
>
>
>
> Explain verbose output (set enable_seqscan = on):
>
>
>
> HashAggregate  (cost=124392.54..124392.65 rows=9 width=37) (actual
> time=7765.650..7765.654 rows=4 loops=1)
>  ->  Nested Loop  (cost=2417.68..124392.49 rows=9 width=37) (actual
> time=1706.703..7765.611 rows=11 loops=1)
>        ->  Nested Loop  (cost=2417.68..123868.75 rows=1807 width=70)
> (actual time=36.374..7706.677 rows=3174 loops=1)
>              ->  Hash Join  (cost=2417.68..119679.50 rows=1807
> width=37) (actual time=36.319..7602.221 rows=3174 loops=1)
>                    Hash Cond: (l.visitorid = v.id)
>                    ->  Seq Scan on itemexperiencelog l
> (cost=0.00..107563.09 rows=2581509 width=70) (actual
> time=0.010..4191.251 rows=2579880 loops=1)
>                    ->  Hash  (cost=2401.43..2401.43 rows=1300
> width=33) (actual time=3.673..3.673 rows=897 loops=1)
>                          ->  Bitmap Heap Scan on visitors v
> (cost=22.48..2401.43 rows=1300 width=33) (actual time=0.448..2.523
> rows=897 loops=1)
>                                Recheck Cond: (userid =
> 'fbe2537f21d94f519605612c0bf7c2c5'::bpchar)
>                                ->  Bitmap Index Scan on
> visitors_userid_index2  (cost=0.00..22.16 rows=1300 width=0) (actual
> time=0.322..0.322 rows=897 loops=1)
>                                      Index Cond: (userid =
> 'fbe2537f21d94f519605612c0bf7c2c5'::bpchar)
>              ->  Index Scan using items_primary_pkey on items_primary
> p  (cost=0.00..2.31 rows=1 width=66) (actual time=0.027..0.029 rows=1
> loops=3174)
>                    Index Cond: (p.id = l.itemid)
>        ->  Index Scan using feeds_pkey on feeds f  (cost=0.00..0.28
> rows=1 width=33) (actual time=0.016..0.016 rows=0 loops=3174)
>              Index Cond: (f.id = p.feedid)
>              Filter: (lower((f.slug)::text) =
> 'wealth_building_by_nightingaleconant'::text)
> Total runtime: 7765.767 ms
>
>
>
> Explain verbose output (set enable_seqscan = off):
>
>
>
> HashAggregate  (cost=185274.71..185274.82 rows=9 width=37) (actual
> time=185.024..185.028 rows=4 loops=1)
>  ->  Nested Loop  (cost=0.00..185274.67 rows=9 width=37) (actual
> time=0.252..184.989 rows=11 loops=1)
>        ->  Nested Loop  (cost=0.00..184751.21 rows=1806 width=70)
> (actual time=0.223..134.943 rows=3174 loops=1)
>              ->  Nested Loop  (cost=0.00..180564.28 rows=1806
> width=37) (actual time=0.192..60.214 rows=3174 loops=1)
>                    ->  Index Scan using visitors_userid_index2 on
> visitors v  (cost=0.00..2580.97 rows=1300 width=33) (actual
> time=0.052..2.342 rows=897 loops=1)
>                          Index Cond: (userid =
> 'fbe2537f21d94f519605612c0bf7c2c5'::bpchar)
>                    ->  Index Scan using
> itemexperiencelog__index__visitorid on itemexperiencelog l
> (cost=0.00..134.04 rows=230 width=70) (actual time=0.013..0.040 rows=4
> loops=897)
>                          Index Cond: (l.visitorid = v.id)
>              ->  Index Scan using items_primary_pkey on items_primary
> p  (cost=0.00..2.31 rows=1 width=66) (actual time=0.019..0.020 rows=1
> loops=3174)
>                    Index Cond: (p.id = l.itemid)
>        ->  Index Scan using feeds_pkey on feeds f  (cost=0.00..0.28
> rows=1 width=33) (actual time=0.014..0.014 rows=0 loops=3174)
>              Index Cond: (f.id = p.feedid)
>              Filter: (lower((f.slug)::text) =
> 'wealth_building_by_nightingaleconant'::text)
> Total runtime: 185.117 ms
>
>
>
> The relevent portions of postgresql.conf:
>
>
> max_connections = 100
> shared_buffers = 2GB
> temp_buffers = 32MB
> work_mem = 64MB
> maintenance_work_mem = 256MB
> max_stack_depth = 8MB
> wal_buffers = 1MB
> checkpoint_segments = 32
> random_page_cost = 2.0
> effective_cache_size = 12GB
> default_statistics_target = 100
>
>
>
> The tables and the indexes that matter:
>
>
>
> CREATE TABLE itemexperiencelog
> (
>  id integer NOT NULL DEFAULT nextval('itemexperiencelog__sequence'::regclass),
>  visitorid character(32) NOT NULL,
>  itemid character(32) NOT NULL,
>  created timestamp without time zone NOT NULL,
>  modified timestamp without time zone NOT NULL,
>  "position" integer NOT NULL DEFAULT 0,
>  itemlength integer NOT NULL DEFAULT 0,
>  usercomplete boolean NOT NULL DEFAULT false,
>  contentcomplete boolean NOT NULL DEFAULT false,
>  source character varying(32) NOT NULL,
>  sessionid character(32) NOT NULL,
>  authenticatedatcreation boolean NOT NULL DEFAULT false,
>  CONSTRAINT itemexperiencelog_pkey PRIMARY KEY (id),
>  CONSTRAINT itemexperiencelog_itemid_fkey FOREIGN KEY (itemid)
>      REFERENCES items_primary (id) MATCH SIMPLE
>      ON UPDATE NO ACTION ON DELETE NO ACTION
> )
>
> CREATE INDEX itemexperiencelog__index__itemid
>  ON itemexperiencelog
>  USING btree
>  (itemid);
>
> CREATE INDEX itemexperiencelog__index__visitorid
>  ON itemexperiencelog
>  USING btree
>  (visitorid);
>
>
>
> CREATE TABLE items_primary
> (
>  id character(32) NOT NULL,
>  feedid character(32),
>  slug character varying(255),
>  pubdate timestamp without time zone,
>  isvisible boolean,
>  deleted integer,
>  itemgroupid integer,
>  lockedflags integer NOT NULL,
>  CONSTRAINT items_primary_pkey PRIMARY KEY (id),
>  CONSTRAINT items_itemgroupid_fkey FOREIGN KEY (itemgroupid)
>      REFERENCES itemgroups (id) MATCH SIMPLE
>      ON UPDATE NO ACTION ON DELETE NO ACTION,
>  CONSTRAINT items_primary_feedid_fkey FOREIGN KEY (feedid)
>      REFERENCES feeds (id) MATCH SIMPLE
>      ON UPDATE NO ACTION ON DELETE NO ACTION
> )
> WITH (OIDS=FALSE);
>
> CREATE INDEX items_primary_feedid_index
>  ON items_primary
>  USING btree
>  (feedid);
>
>
>
> CREATE TABLE feeds
> (
>  id character(32) NOT NULL,
>  rssupdateinterval integer,
>  lastrssupdate timestamp without time zone,
>  nextrssupdate timestamp without time zone,
>  url text NOT NULL,
>  title text NOT NULL,
>  subtitle text,
>  link text,
>  slug character varying(2048) NOT NULL,
>  description text,
>  lang character varying(255),
>  copyright text,
>  pubdate timestamp without time zone,
>  lastbuilddate character varying(255),
>  docs text,
>  generator character varying(255),
>  managingeditor character varying(255),
>  webmaster character varying(255),
>  status integer,
>  ttl character varying(255),
>  image_title text,
>  image_url text,
>  image_link text,
>  image_description text,
>  image_width integer,
>  image_height integer,
>  rating character varying(255),
>  skiphours character varying(255),
>  skipdays character varying(255),
>  genretagid character(32),
>  sourceuserid character(32),
>  created timestamp without time zone NOT NULL,
>  deleted integer NOT NULL,
>  cloud_domain character varying(255),
>  cloud_port character varying(255),
>  cloud_path character varying(255),
>  cloud_registerprocedure character varying(255),
>  cloud_protocol character varying(255),
>  itunesauthor character varying(255),
>  itunesblock character varying(255),
>  itunescategories text,
>  itunesimage character varying(255),
>  itunesexplicit character varying(255),
>  ituneskeywords text,
>  itunesnewfeedurl character varying(255),
>  itunesowner_name character varying(255),
>  itunesowner_email character varying(255),
>  itunessubtitle text,
>  itunessummary text,
>  yahooimage text,
>  modified timestamp without time zone NOT NULL,
>  mediatype integer,
>  isvisible boolean NOT NULL DEFAULT false,
>  mediaplayertype integer NOT NULL,
>  episodebrowsecount integer,
>  comments text NOT NULL DEFAULT ''::text,
>  lockedflags integer NOT NULL DEFAULT 0,
>  sequenceid integer NOT NULL DEFAULT nextval('feeds_sequence'::regclass),
>  feedgroupid character(32),
>  bannerurl text,
>  categories text NOT NULL,
>  publisher text,
>  episodefetchstrategy integer NOT NULL,
>  averageuserrating real,
>  userratingscount integer,
>  lastupdate timestamp without time zone NOT NULL,
>  userratingstotal double precision NOT NULL,
>  CONSTRAINT feeds_pkey PRIMARY KEY (id),
>  CONSTRAINT feeds_feedgroupid_fkey FOREIGN KEY (feedgroupid)
>      REFERENCES feedgroups (id) MATCH SIMPLE
>      ON UPDATE NO ACTION ON DELETE NO ACTION,
>  CONSTRAINT fk5cb07d0e1080d15d FOREIGN KEY (sourceuserid)
>      REFERENCES users (id) MATCH SIMPLE
>      ON UPDATE NO ACTION ON DELETE NO ACTION,
>  CONSTRAINT fk5cb07d0eb113835f FOREIGN KEY (genretagid)
>      REFERENCES tags (id) MATCH SIMPLE
>      ON UPDATE NO ACTION ON DELETE NO ACTION,
>  CONSTRAINT feeds_slug_key UNIQUE (slug)
> )
> WITH (OIDS=FALSE);
>
> CREATE UNIQUE INDEX feeds_slug_unique
>  ON feeds
>  USING btree
>  (lower(slug::text));
>
>
>
> CREATE TABLE visitors
> (
>  id character(32) NOT NULL,
>  visitorid character(32) NOT NULL,
>  userid character(32),
>  sessionid text NOT NULL,
>  created timestamp without time zone NOT NULL,
>  modified timestamp without time zone NOT NULL,
>  deleted integer NOT NULL,
>  sequenceid integer DEFAULT nextval('visitors_sequence'::regclass),
>  CONSTRAINT visitors_pkey PRIMARY KEY (id)
> )
> WITH (OIDS=FALSE);
>
> CREATE INDEX visitors_userid_index2
>  ON visitors
>  USING btree
>  (userid);
>
> CREATE INDEX visitors_visitorid_index2
>  ON visitors
>  USING btree
>  (visitorid);
>

Responses

Browse pgsql-performance by date

  From Date Subject
Next Message Ron 2009-03-24 22:58:13 Re: High CPU Utilization
Previous Message Bryan Murphy 2009-03-24 22:21:28 Re: Help Me Understand Why I'm Getting a Bad Query Plan