Index Ignored Due To Use Of View - Mailing list pgsql-bugs

From Donald Fraser
Subject Index Ignored Due To Use Of View
Date
Msg-id 7C3EA8B4867547AC899AD3EC43DEA6AA@DEVELOP1
Whole thread Raw
List pgsql-bugs
PostgreSQL 8.3.14
OS: Linux Redhat 5.4

Note: I have used the same subject for this email taken from an email: Post=
ed 2011-02-24 13:29:22-08 by "David Johnston", because this seems to be a v=
ery similar observation.

Bug/Problem Summary:
We are using a simple query based on a simple view and the query optimizer =
is not choosing an index.=20
The same query without the view is using an index.
The same query on an almost identical view, but having either removed a sin=
gle column which was generated via a function call or replace the function =
call with equivalent SQL, then the query optimizer is choosing an index.

Other notes:
We observe the same behaviour on two separate databases running on separate=
 servers (both the same version).
The genetic query optimizer settings are all on defaults for these versions.

Details;
With the following view:

CREATE OR REPLACE VIEW vu_tbl_news_web AS=20
SELECT=20
 n.id, n.id_cmpy, n.id_news, n.id_newshdline,=20
 n.s_origcmpyname, n.s_hdline, n.s_news,=20
 n.b_amend, n.b_replace,=20
 n.dt_publish,=20
 n.tsv_hdline, n.tsv_news,=20
 n.b_hasorigdoc,=20
 (SELECT h.s_hdline FROM tbl_newshdline h WHERE h.id =3D n.id_newshdline LI=
MIT 1) AS s_hdlinetype,=20
 get_cmpyname(n.id_contrib) AS s_provider
FROM  tbl_news n
WHERE  n.dt_publish IS NOT NULL;

Query:
SELECT  n.id, n.id_cmpy, n.s_origcmpyname,=20
 n.s_hdline, n.dt_publish=20
FROM  vu_tbl_news_web n=20
ORDER BY n.dt_publish DESC=20
LIMIT 25

Analyse produces:
Limit  (cost=3D180017.37..180017.43 rows=3D25 width=3D80)
  ->  Sort  (cost=3D180017.37..180110.54 rows=3D37267 width=3D80)
        Sort Key: n.dt_publish
        ->  Subquery Scan n  (cost=3D0.00..178965.72 rows=3D37267 width=3D8=
0)
              ->  Seq Scan on tbl_news n  (cost=3D0.00..178593.05 rows=3D37=
267 width=3D1152)
                    Filter: (dt_publish IS NOT NULL)
                    SubPlan
                      ->  Limit  (cost=3D0.00..4.29 rows=3D1 width=3D22)
                            ->  Seq Scan on tbl_newshdline h  (cost=3D0.00.=
.4.29 rows=3D1 width=3D22)
                                  Filter: (id =3D $0)

Although the number of rows (37k) is small, there is a lot of data in some =
of the columns so, with a seq. scan its taking nearly 2 seconds. Compared t=
o 16ms when using an index.

Now if I perform the same query without using the view, such as:

SELECT  n.id, n.id_cmpy, n.s_origcmpyname,=20
 n.s_hdline, n.dt_publish=20
FROM  tbl_news n=20
WHERE  n.dt_publish IS NOT NULL=20
ORDER BY n.dt_publish DESC=20
LIMIT 25

Analyse produces:
Limit  (cost=3D0.00..21.34 rows=3D25 width=3D73)
  ->  Index Scan Backward using tbl_news_publish1_key on tbl_news n  (cost=
=3D0.00..31807.05 rows=3D37267 width=3D73)

Finally I discovered that if I remove a column from the view, that is gener=
ated via a function, then all works as expected?

CREATE OR REPLACE VIEW vu_tbl_news_web3 AS=20
SELECT=20
 n.id, n.id_cmpy, n.id_news, n.id_newshdline,=20
 n.s_origcmpyname, n.s_hdline, n.s_news,=20
 n.b_amend, n.b_replace,=20
 n.dt_publish, n.tsv_hdline, n.tsv_news,=20
 n.b_hasorigdoc,
 (SELECT h.s_hdline FROM tbl_newshdline h WHERE h.id =3D n.id_newshdline LI=
MIT 1) AS s_hdlinetype
FROM  tbl_news n
WHERE  n.dt_publish IS NOT NULL;

SELECT  n.id, n.id_cmpy, n.s_origcmpyname,=20
 n.s_hdline, n.dt_publish=20
FROM  vu_tbl_news_web3 n=20
ORDER BY n.dt_publish DESC=20
LIMIT 25

Analyse produces:
Limit  (cost=3D0.00..21.34 rows=3D25 width=3D73)
  ->  Index Scan Backward using tbl_news_publish1_key on tbl_news n  (cost=
=3D0.00..31807.05 rows=3D37267 width=3D73)

The definition of the function used is:
CREATE OR REPLACE FUNCTION get_cmpyname(integer)  RETURNS citext AS
$BODY$
DECLARE
 idcmpy ALIAS FOR $1;
 sumb citext;
 sres citext;
BEGIN
 SELECT INTO sumb, sres s_umbname, s_name FROM tbl_cmpy WHERE (id =3D idcmp=
y) LIMIT 1;
 IF length(sumb) > 0 THEN
  sres :=3D  sumb || ' - ' || sres;
 END IF;
 RETURN sres;
END $BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT SECURITY DEFINER COST 100;

I also noted that if I replace the function call in the view with equivalen=
t SQL:
(SELECT (CASE WHEN length(c.s_umbname) > 0 THEN c.s_umbname || ' - '::citex=
t || c.s_name ELSE c.s_name END) AS s_cmpyname FROM tbl_cmpy c WHERE c.id =
=3D n.id_contrib LIMIT 1) AS s_provider
the problem also goes away.

Regards
Donald Fraser=

pgsql-bugs by date:

Previous
From: Alex Lai
Date:
Subject: Re: postgres 9 streaming replication
Next
From: "Donald Fraser"
Date:
Subject: Re: Index Ignored Due To Use Of View