optimizer behavior in the case of highly updated tables

--_000_FD020D3E50E7FA479567872E5F5F31E304599C0B41ex01corpql2 co_
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

I am looking for some specific information regarding optimizer behavior.
We recently experienced a situation where a query that was previously using=
a btree lookup (efficient) SWITCHED to using seqscan/hash lookup.

My questions would be:


- Under what circumstances is the optimizer likely to CHANGE behav=
ior from using a btree index lookup to using a seq scan/hash lookup?

- What are the critical decision factors that would feed into the =
optimizer making such a change?

- Is it possible to measure any metrics in a way that would enable=
a prediction of such a change?

Platform


- 8.3.10 (64bit) on RHEL5.

- Linux xxxxx 2.6.18-164.10.1.el5xen #1 SMP Thu Jan 7 20:28:30 EST=
2010 x86_64 x86_64 x86_64 GNU/Linux

Application
The table in question is:

- 30m rows, variable length (contains varchar fields), rowlength a=
vg about 120B

- Approx. 3m unique values in the index column

Activity on the table would be, per row: "Insert, multiple updates, delete=
after 90 days"

We vacuum analyze this table once/weekly.
No partitions are used.

Our experience which prompts this question was as follows:

- If the table is not "vacuum analyze'd" at least once/week, the q=
uery plans become unpredictable as to whether they will use btree or seqsca=
n/hash lookup

- Until last week, "vacuum analyze" was sufficient

- Friday evening of last week, the query plan for selected queries=
against this index changed again, but "vacuum analyze" was insufficient

- Rebuilding index on primary key and on the column index was insu=
fficient

- It was necessary to take a site outage and perform a "vacuum ful=
l analyze" on the table

- Following this, the query plan reverted to the more efficient bt=
ree lookup

Clearly, the garbage buildup resulting from transaction activity on the tab=
le is the villain here.

- Is it possible to calculate expected space usage given row count=
and average row size

- At what point might the ratio of "expected"/"actual" space usage=
be able to indicate the need to perform "full vacuum", or similar maintena=
nce

Any observations/comments that anyone would care to make are welcome.
Thanks in advance for your time
Mr





--_000_FD020D3E50E7FA479567872E5F5F31E304599C0B41ex01corpql2 co_
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40"><head><meta http-equiv=3DContent-Type content=
=3D"text/html; charset=3Dus-ascii"><meta name=3DGenerator content=3D"Micros=
oft Word 14 (filtered medium)"><style><!--
/* Font Definitions */
[at] font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
[at] font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
[at] font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
{mso-style-priority:34;
margin-top:0in;
margin-right:0in;
margin-bottom:0in;
margin-left:.5in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri","sans-serif";
color:windowtext;}
..MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri","sans-serif";}
[at] page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
[at] list l0
{mso-list-id:200435502;
mso-list-type:hybrid;
mso-list-template-ids:276080712 1587193646 67698691 67698693 67698689 6769=
8691 67698693 67698689 67698691 67698693;}
[at] list l0:level1
{mso-level-start-at:0;
mso-level-number-format:bullet;
mso-level-text:-;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Calibri","sans-serif";
mso-fareast-font-family:Calibri;}
[at] list l0:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l0:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l0:level4
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
[at] list l0:level5
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l0:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l0:level7
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
[at] list l0:level8
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l0:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l1
{mso-list-id:244537712;
mso-list-type:hybrid;
mso-list-template-ids:-36948388 301990720 67698691 67698693 67698689 67698=
691 67698693 67698689 67698691 67698693;}
[at] list l1:level1
{mso-level-start-at:0;
mso-level-number-format:bullet;
mso-level-text:-;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Calibri","sans-serif";
mso-fareast-font-family:Calibri;}
[at] list l1:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l1:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l1:level4
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
[at] list l1:level5
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l1:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l1:level7
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
[at] list l1:level8
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l1:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l2
{mso-list-id:909273941;
mso-list-type:hybrid;
mso-list-template-ids:-379690606 -1625513328 67698691 67698693 67698689 67=
698691 67698693 67698689 67698691 67698693;}
[at] list l2:level1
{mso-level-start-at:0;
mso-level-number-format:bullet;
mso-level-text:-;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Calibri","sans-serif";
mso-fareast-font-family:Calibri;}
[at] list l2:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l2:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l2:level4
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
[at] list l2:level5
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l2:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
[at] list l2:level7
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
[at] list l2:level8
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
[at] list l2:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
ol
{margin-bottom:0in;}
ul
{margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]--></head><body lang=3DEN-US link=3Dblue vli=
nk=3Dpurple><div class=3DWordSection1><p class=3DMsoNormal>I am looking for=
some specific information regarding optimizer behavior.<o:p></o:p></p><p c=
lass=3DMsoNormal>We recently experienced a situation where a query that was=
previously using a btree lookup (efficient) SWITCHED to using seqscan/hash=
lookup.<o:p></o:p></p><p class=3DMsoNormal><o:p> </o:p></p><p class=
=3DMsoNormal>My questions would be:<o:p></o:p></p><p class=3DMsoNormal><o:p=
> </o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25in;ms=
o-list:l0 level1 lfo2'><![if !supportLists]><span style=3D'mso-list:Ignore'=
>-<span style=3D'font:7.0pt "Times New Roman"'>    &nbs=
p;     </span></span><![endif]>Under what circumstances=
is the optimizer likely to CHANGE behavior from using a btree index lookup=
to using a seq scan/hash lookup?<o:p></o:p></p><p class=3DMsoListParagraph=
style=3D'text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]>=
<span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times New Roman=
"'>          </span></span><![=
endif]>What are the critical decision factors that would feed into the opti=
mizer making such a change?<o:p></o:p></p><p class=3DMsoListParagraph style=
=3D'text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span =
style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times New Roman"'>&nb=
sp;         </span></span><![endif]=
>Is it possible to measure any metrics in a way that would enable a predict=
ion of such a change?<o:p></o:p></p><p class=3DMsoNormal><o:p> </o:p><=
/p><p class=3DMsoNormal>Platform<o:p></o:p></p><p class=3DMsoNormal><o:p>&n=
bsp;</o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25in;mso-l=
ist:l0 level1 lfo2'><![if !supportLists]><span style=3D'mso-list:Ignore'>-<=
span style=3D'font:7.0pt "Times New Roman"'>     &=
nbsp;    </span></span><![endif]>8.3.10 (64bit) on RHEL5.<o:=
p></o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25in;mso-lis=
t:l0 level1 lfo2'><![if !supportLists]><span style=3D'mso-list:Ignore'>-<sp=
an style=3D'font:7.0pt "Times New Roman"'>     &nb=
sp;    </span></span><![endif]>Linux xxxxx 2.6.18-164.10.1.e=
l5xen #1 SMP Thu Jan 7 20:28:30 EST 2010 x86_64 x86_64 x86_64 GNU/Linux<o:p=
></o:p></p><p class=3DMsoNormal><o:p> </o:p></p><p class=3DMsoNormal>A=
pplication<o:p></o:p></p><p class=3DMsoNormal>The table in question is:<o:p=
></o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25in;mso-list=
:l2 level1 lfo1'><![if !supportLists]><span style=3D'mso-list:Ignore'>-<spa=
n style=3D'font:7.0pt "Times New Roman"'>     &nbs=
p;    </span></span><![endif]>30m rows, variable length (con=
tains varchar fields), rowlength avg about 120B<o:p></o:p></p><p class=3DMs=
oListParagraph style=3D'text-indent:-.25in;mso-list:l2 level1 lfo1'><![if !=
supportLists]><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "T=
imes New Roman"'>          </s=
pan></span><![endif]>Approx. 3m unique values in the index column<o:p></o:p=
></p><p class=3DMsoNormal><o:p> </o:p></p><p class=3DMsoNormal>Activit=
y on the table would be, per row:  “Insert, multiple updates, de=
lete after 90 days”<o:p></o:p></p><p class=3DMsoNormal><o:p> </o=
:p></p><p class=3DMsoNormal>We vacuum analyze this table once/weekly.<o:p><=
/o:p></p><p class=3DMsoNormal>No partitions are used.<o:p></o:p></p><p clas=
s=3DMsoNormal><o:p> </o:p></p><p class=3DMsoNormal>Our experience whic=
h prompts this question was as follows:<o:p></o:p></p><p class=3DMsoListPar=
agraph style=3D'text-indent:-.25in;mso-list:l2 level1 lfo1'><![if !supportL=
ists]><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times New=
Roman"'>          </span></sp=
an><![endif]>If the table is not “vacuum analyze’d” at le=
ast once/week, the query plans become unpredictable as to whether they will=
use btree or seqscan/hash lookup<o:p></o:p></p><p class=3DMsoListParagraph=
style=3D'text-indent:-.25in;mso-list:l2 level1 lfo1'><![if !supportLists]>=
<span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times New Roman=
"'>          </span></span><![=
endif]>Until last week, “vacuum analyze” was sufficient<o:p></o=
:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25in;mso-list:l2 =
level1 lfo1'><![if !supportLists]><span style=3D'mso-list:Ignore'>-<span st=
yle=3D'font:7.0pt "Times New Roman"'>      &n=
bsp;   </span></span><![endif]>Friday evening of last week, the q=
uery plan for selected queries against this index changed again, but “=
;vacuum analyze” was insufficient<o:p></o:p></p><p class=3DMsoListPar=
agraph style=3D'text-indent:-.25in;mso-list:l2 level1 lfo1'><![if !supportL=
ists]><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times New=
Roman"'>          </span></sp=
an><![endif]>Rebuilding index on primary key and on the column index was in=
sufficient<o:p></o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-=
..25in;mso-list:l2 level1 lfo1'><![if !supportLists]><span style=3D'mso-list=
:Ignore'>-<span style=3D'font:7.0pt "Times New Roman"'>   &n=
bsp;      </span></span><![endif]>It was necessary=
to take a site outage and perform a “vacuum full analyze” on t=
he table<o:p></o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.2=
5in;mso-list:l2 level1 lfo1'><![if !supportLists]><span style=3D'mso-list:I=
gnore'>-<span style=3D'font:7.0pt "Times New Roman"'>   &nbs=
p;      </span></span><![endif]>Following this, th=
e query plan reverted to the more efficient btree lookup<o:p></o:p></p><p c=
lass=3DMsoNormal><o:p> </o:p></p><p class=3DMsoNormal>Clearly, the gar=
bage buildup resulting from transaction activity on the table is the villai=
n here.<o:p></o:p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25=
in;mso-list:l1 level1 lfo3'><![if !supportLists]><span style=3D'mso-list:Ig=
nore'>-<span style=3D'font:7.0pt "Times New Roman"'>    =
;      </span></span><![endif]>Is it possible to c=
alculate expected space usage given row count and average row size<o:p></o:=
p></p><p class=3DMsoListParagraph style=3D'text-indent:-.25in;mso-list:l1 l=
evel1 lfo3'><![if !supportLists]><span style=3D'mso-list:Ignore'>-<span sty=
le=3D'font:7.0pt "Times New Roman"'>      &nb=
sp;   </span></span><![endif]>At what point might the ratio of &#=
8220;expected”/”actual” space usage be able to indicate t=
he need to perform “full vacuum”, or similar maintenance<o:p></=
o:p></p><p class=3DMsoNormal><o:p> </o:p></p><p class=3DMsoNormal>Any =
observations/comments that anyone would care to make are welcome.<o:p></o:p=
></p><p class=3DMsoNormal>Thanks in advance for your time<o:p></o:p></p><p =
class=3DMsoNormal>Mr<o:p></o:p></p><p class=3DMsoNormal><o:p> </o:p></=
p><p class=3DMsoNormal><o:p> </o:p></p><p class=3DMsoNormal><o:p> =
;</o:p></p><p class=3DMsoNormal><o:p> </o:p></p></div></body></html>=

--_000_FD020D3E50E7FA479567872E5F5F31E304599C0B41ex01corpql2 co_--
Mark Rostron [ Mi, 09 Juni 2010 04:58 ] [ ID #2042910 ]

Re: optimizer behavior in the case of highly updated tables

On Tue, Jun 8, 2010 at 8:58 PM, Mark Rostron <mrostron [at] ql2.com> wrote:
> I am looking for some specific information regarding optimizer behavior.
>
> We recently experienced a situation where a query that was previously using
> a btree lookup (efficient) SWITCHED to using seqscan/hash lookup.

OK, before we go any further, got any explain analyze output of the
fast and slow queries?

--
Sent via pgsql-admin mailing list (pgsql-admin [at] postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-admin
Scott Marlowe [ Mi, 09 Juni 2010 07:54 ] [ ID #2042912 ]

Re: optimizer behavior in the case of highly updated tables

Mark Rostron wrote:
>
> - It was necessary to take a site outage and perform a =93vacuum full
> analyze=94 on the table
>
> - Following this, the query plan reverted to the more efficient btree
> lookup
>
> Clearly, the garbage buildup resulting from transaction activity on
> the table is the villain here.
>
> - Is it possible to calculate expected space usage given row count and
> average row size
>
> - At what point might the ratio of =93expected=94/=94actual=94 space us=
age be
> able to indicate the need to perform =93full vacuum=94, or similar main=
tenance
>

I think you're right to focus on this part, because with your usage
pattern--deleting all old data constantly--you have to get this under
control in order for the query planner to do the right thing here.

Start by reading http://wiki.postgresql.org/wiki/VACUUM_FULL

What you probably should have done in order to return to sane query
plans was to run CLUSTER instead of VACUUM FULL. Site would have been
down less time, and you actually made some future problems a bit worse
by screwing your indexes up some using the problematic FULL.

As for measuring what's going wrong here, what you want to do is run
this around once a week during a slow period and save the output for
analysis:

VACUUM VERBOSE;

This will give you a bunch of statistics about space usage, including a
summary at the end that will tell if there's a serious problem you might
already be running into (running out of space in the free space map).
Combine that with a look at pg_stat_user_tables and you should have a
decent initial statistical picture of what's going on with your data.

There are two large scale things you may need to consider if volume on
your site expands in the future:

1) Deleting the historical data in smaller chunks and doing an immediate
VACUUM afterwards. Perhaps as often as daily. This keeps the amount of
dead space VACUUM has to clean up as small as possible, at the expensive
of higher site overhead.

2) Start partitioning your tables. This allows you to just DROP old
partitions rather than deleting rows from a single master table. It can
make this whole class of problem go away.

--
Greg Smith 2ndQuadrant US Baltimore, MD
PostgreSQL Training, Services and Support
greg [at] 2ndQuadrant.com www.2ndQuadrant.us


--
Sent via pgsql-admin mailing list (pgsql-admin [at] postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-admin
Greg Smith [ Mi, 09 Juni 2010 08:04 ] [ ID #2042914 ]

Re: optimizer behavior in the case of highly updated tables

On Wed, Jun 9, 2010 at 12:04 AM, Greg Smith <greg [at] 2ndquadrant.com> wrote:
> Mark Rostron wrote:
>>
>> - It was necessary to take a site outage and perform a =93vacuum full
>> analyze=94 on the table
>>
>> - Following this, the query plan reverted to the more efficient btree
>> lookup
>>
>> Clearly, the garbage buildup resulting from transaction activity on the
>> table is the villain here.
>>
>> - Is it possible to calculate expected space usage given row count and
>> average row size
>>
>> - At what point might the ratio of =93expected=94/=94actual=94 space usa=
ge be able
>> to indicate the need to perform =93full vacuum=94, or similar maintenance
>>
>
> I think you're right to focus on this part, because with your usage
> pattern--deleting all old data constantly--you have to get this under
> control in order for the query planner to do the right thing here.

I think this is one of those places where you need to vacuum more
often and more aggresively to keep up. If the usage pattern works
well with truncating partitions then do that. But it's possible that
aggresive vacuuming can take care of this.

I wonder what vacuum verbose before and after the performance shift
would reveal anything useful about bloating.

--
Sent via pgsql-admin mailing list (pgsql-admin [at] postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-admin
Scott Marlowe [ Mi, 09 Juni 2010 08:08 ] [ ID #2042915 ]
Datenbanken » gmane.comp.db.postgresql.admin » optimizer behavior in the case of highly updated tables

Vorheriges Thema: Details about pg_stat_bgwriter
Nächstes Thema: Convite para se conectar no LinkedIn