Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-07-22 Thread Kyotaro HORIGUCHI
Hello, I'm very sory to take your time on this mess.

ul 2013 16:06:11 +0530, Amit Kapila amit.kap...@huawei.com wrote in 
014201ce7bc6$f71eb950$e55c2bf0$@kap...@huawei.com
 I understood your patch's algorithm, but still I have doubt in my mind that
 if the next analyze can correct the estimates,
 Why would that be not sufficient. Please refer my last mail for analysis of
 same 
 http://www.postgresql.org/message-id/000601ce77ad$7d3388e0$779a9aa0$@kapila@
 huawei.com

Hmm. I've reconfirmed what was happened on my test set.

As the result, the misestimation with dead_tup = 0 which I
thought to observe has turned out to be an illusion..

Tuple number estimation is working as it is expected.

I withdraw this patch.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-07-08 Thread Amit Kapila
On Wednesday, July 03, 2013 1:21 PM Kyotaro HORIGUCHI wrote:
 Hello,
 
  I could see the same output with your latest script, also I could
 reproduce
  the test if I run the test with individual sql statements.
  One of the main point for reproducing individual test was to keep
 autovacuum
  = off.
 
 I see. Autovacuum's nap time is 60 sconds for the default
 settings. Your operation might help it to snipe the window
 between the last massive delete and the next explict vacuum in
 store_result().. Anyway setting autovacuum to off should aid to
 make clean environment fot this issue.

  Now I can look into it further, I have still not gone through in
 detail
  about your new approach to calculate the reltuples, but I am
 wondering
  whether there can be anyway with which estimates can be improved with
  different calculation in vac_estimate_reltuples().
 
 I'll explain this in other words alghough It might be
 repetitious.
 
 It is tough to decide how to modify there. Currently I decided to
 preserve vac_estimate_reltuples as possible as it is. For that
 objective, I picked up old_rel_tuples as intermediate variable
 for the aid to 'deceive' the function. This can be different form
 deciding to separate this estimation function from that for
 analyze.
 
 As I described before, vac_estimates_reltuples has a presumption
 that the tuple density in skipped pages is not so different from
 that in whole table before vacuuming. Since the density is
 calculated without using any hint about the skipped pages, and it
 cannot tell how much tuples aganst pg_class.reltuples is already
 dead, the value can be far different from the true one and cannot
 be verified. Given that we canot use
 pg_stat_user_tables.n_dead_tup, reading all pages can fix it but
 the penalty should be intolerable.
 
 Using FSM to know the used bytes in skipped pages (which is all
 visible by the definition) seems to give good estimations of the
 tuples in the skipped pages to some extent assuming the
 uniformity of tuple length. Of course strong deviation in length
 can deceive the algorithm.
 
 Does it make sense for you?

I understood your patch's algorithm, but still I have doubt in my mind that
if the next analyze can correct the estimates,
Why would that be not sufficient. Please refer my last mail for analysis of
same 
http://www.postgresql.org/message-id/000601ce77ad$7d3388e0$779a9aa0$@kapila@
huawei.com

Performance Data
--
I have checked few cases where FSM is not updated accurately, this patch
seems to give much worse results than current code.

Test with Patch

1. Test given by you where tuple density is non-uniform

postgres=# drop table if exists t; 
DROP TABLE 
postgres=# create table t (a int, b int, c int, d int default 0, e int
default 0 
, f int default 0); 
CREATE TABLE 
postgres=# insert into t (select a, (random() * 10)::int from
generate_serie 
s((select count(*) from t) + 1, 100) a); 
INSERT 0 100 
postgres=# update t set b = b + 1 where a   (select count(*) from t) * 0.7;

UPDATE 69 
postgres=# vacuum t; 
VACUUM 
postgres=# delete from t where a  (select count(*) from t) * 0.99; 
DELETE 98 
postgres=# vacuum t; 
VACUUM 
postgres=# select c.relpages, s.n_live_tup, c.reltuples, (select count(*)
from t 
) as tuples, reltuples::float / (select count(*) from t) as ratio  from
pg_stat_ 
user_tables s, pg_class c where s.relname = 't' and c.relname = 't'; 
 relpages | n_live_tup | reltuples | tuples |  ratio 
--++---++-- 
 6370 |  13596 | 13596 |  10001 | 1.35946405359464 
(1 row) 

2. Test where tuple density is non-uniform and FSM updates before
calculation in Vacuum are not accurate.
   I have created index on table to simulate this test

postgres=# drop table if exists t; 
DROP TABLE 
postgres=# create table t (a int, b int, c int, d int default 0, e int
default 0 
, f int default 0); 
CREATE TABLE 
postgres=# create index on t(a); 
CREATE INDEX 
postgres=# insert into t (select a, (random() * 10)::int from
generate_serie 
s((select count(*) from t) + 1, 100) a); 
INSERT 0 100 
postgres=# update t set b = b + 1 where a   (select count(*) from t) * 0.7;

UPDATE 69 
postgres=# vacuum t; 
VACUUM 
postgres=# delete from t where a  (select count(*) from t) * 0.99; 
DELETE 98 
postgres=# vacuum t; 
VACUUM 
postgres=# select c.relpages, s.n_live_tup, c.reltuples, (select count(*)
from t 
) as tuples, reltuples::float / (select count(*) from t) as ratio  from
pg_stat_ 
user_tables s, pg_class c where s.relname = 't' and c.relname = 't'; 
 relpages | n_live_tup |  reltuples   | tuples |  ratio 
--++--++-- 
 6370 |1001327 | 1.00133e+006 |  10001 | 100.122687731227 
(1 row)

Now this result in tuple estimation worse than current code.

I think we need to have more tests to show that new calculation is better in
all cases than 

Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-07-08 Thread Josh Berkus
On 07/03/2013 12:51 AM, Kyotaro HORIGUCHI wrote:
 It is tough to decide how to modify there. Currently I decided to
 preserve vac_estimate_reltuples as possible as it is. For that
 objective, I picked up old_rel_tuples as intermediate variable
 for the aid to 'deceive' the function. This can be different form
 deciding to separate this estimation function from that for
 analyze.

Kyotaro, do you think you'll be revising this patch in the next 2 days,
or should I bounce it, and you can resubmit it for the next commitfest?

-- 
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-07-03 Thread Kyotaro HORIGUCHI
Hello,

 I could see the same output with your latest script, also I could reproduce
 the test if I run the test with individual sql statements.
 One of the main point for reproducing individual test was to keep autovacuum
 = off.

I see. Autovacuum's nap time is 60 sconds for the default
settings. Your operation might help it to snipe the window
between the last massive delete and the next explict vacuum in
store_result().. Anyway setting autovacuum to off should aid to
make clean environment fot this issue.

 Now I can look into it further, I have still not gone through in detail
 about your new approach to calculate the reltuples, but I am wondering
 whether there can be anyway with which estimates can be improved with
 different calculation in vac_estimate_reltuples().

I'll explain this in other words alghough It might be
repetitious.

It is tough to decide how to modify there. Currently I decided to
preserve vac_estimate_reltuples as possible as it is. For that
objective, I picked up old_rel_tuples as intermediate variable
for the aid to 'deceive' the function. This can be different form
deciding to separate this estimation function from that for
analyze.

As I described before, vac_estimates_reltuples has a presumption
that the tuple density in skipped pages is not so different from
that in whole table before vacuuming. Since the density is
calculated without using any hint about the skipped pages, and it
cannot tell how much tuples aganst pg_class.reltuples is already
dead, the value can be far different from the true one and cannot
be verified. Given that we canot use
pg_stat_user_tables.n_dead_tup, reading all pages can fix it but
the penalty should be intolerable.

Using FSM to know the used bytes in skipped pages (which is all
visible by the definition) seems to give good estimations of the
tuples in the skipped pages to some extent assuming the
uniformity of tuple length. Of course strong deviation in length
can deceive the algorithm.

Does it make sense for you?

I might could show the numerical explanation but I'm afraind I
can't do it for now. I'll be able to take time sooner... (also
for reviewing..)

 One thing I have observed that 2nd parameter is_analyze of
 vac_estimate_reltuples() is currently not used.

Mmm, it seems to have been useless from the beginning of the
function...

 I cannot work on it till early next week, so others are welcome to join


regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-07-02 Thread Amit Kapila
On Thursday, June 27, 2013 4:58 PM Amit Kapila wrote:
 On Wednesday, June 26, 2013 7:40 AM Kyotaro HORIGUCHI wrote:
  I've recovered from messing up.
 
  snip
   Please let me have a bit of time to diagnose this.
 
  I was completely messed up and walking on the wrong way. I looked
 into
  the vacuum for UPDATEs, not DELETE's so it's quite resonable to have
  such results.
 
  The renewed test script attached shows the verbose output of vacuum
  after the deletes. I had following output from it.
 
  # I belive this runs for you..
 
  | INFO: t: found 98 removable, 110 nonremovable row
  |   versions in 6308 out of 10829 pages
 
  On such a case of partially-scanned, lazy_scan_heap() tries to
 estimate
  resulting num_tuples in vac_estimate_reltuples() assuming the
  uniformity of tuple density, which failes for such a a strong
 imbalance
  made by bulk updates.
 
  Do you find any differences between what you will have and the
  following I had?
 
 I could see the same output with your latest script, also I could
 reproduce
 the test if I run the test with individual sql statements.
 One of the main point for reproducing individual test was to keep
 autovacuum
 = off.

I checked further that why I could not reproduce the issue with
autovacuum=on.
The reason is that it starts analyzer which changes the value for reltuples
in pg_class and after that the estimated and real values become same.
Kindly refer below code:

relation_needs_vacanalyze() 
{ 
.. 
anltuples = tabentry-changes_since_analyze; 
.. 
anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;
.. 
*doanalyze = (anltuples  anlthresh);
}

Test Results 
--

postgres=# drop table if exists t; 
DROP TABLE 
postgres=# create table t (a int, b int, c int, d int default 0, e int
default 0 
, f int default 0); 
CREATE TABLE 
postgres=# insert into t (select a, (random() * 10)::int from
generate_serie 
s((select count(*) from t) + 1, 100) a); 
INSERT 0 100 
postgres=# update t set b = b + 1 where a   (select count(*) from t) * 0.7;

UPDATE 69 
postgres=# vacuum t; 
VACUUM 
postgres=# delete from t where a  (select count(*) from t) * 0.99; 
DELETE 98 
postgres=# vacuum t; 
VACUUM 
postgres=# select c.relpages, s.n_live_tup, c.reltuples, (select count(*)
from t 
) as tuples, reltuples::float / (select count(*) from t) as ratio  from
pg_stat_ 
user_tables s, pg_class c where s.relname = 't' and c.relname = 't'; 
 relpages | n_live_tup | reltuples | tuples |  ratio 
--++---++-- 
 6370 | 417600 |417600 |  10001 | 41.7558244175582 
(1 row) 

Here I waited for 1 minute (sufficient time so that analyzer should get
trigger if required).
Infact if you run Analyze t, that also would have served the purpose.

postgres=# select c.relpages, s.n_live_tup, c.reltuples, (select count(*)
from t 
) as tuples, reltuples::float / (select count(*) from t) as ratio  from
pg_stat_ 
user_tables s, pg_class c where s.relname = 't' and c.relname = 't'; 
 relpages | n_live_tup | reltuples | tuples | ratio 
--++---++--- 
 6370 |  10001 | 10001 |  10001 | 1 
(1 row)


Now if subsequent analyzer run corrects the estimate, don't you think that
it is sufficient for the problem reported?

With Regards,
Amit Kapila.




-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-27 Thread Amit Kapila
On Wednesday, June 26, 2013 7:40 AM Kyotaro HORIGUCHI wrote:
 I've recovered from messing up.
 
 snip
  Please let me have a bit of time to diagnose this.
 
 I was completely messed up and walking on the wrong way. I looked into
 the vacuum for UPDATEs, not DELETE's so it's quite resonable to have
 such results.
 
 The renewed test script attached shows the verbose output of vacuum
 after the deletes. I had following output from it.
 
 # I belive this runs for you..
 
 | INFO: t: found 98 removable, 110 nonremovable row
 |   versions in 6308 out of 10829 pages
 
 On such a case of partially-scanned, lazy_scan_heap() tries to estimate
 resulting num_tuples in vac_estimate_reltuples() assuming the
 uniformity of tuple density, which failes for such a a strong imbalance
 made by bulk updates.
 
 Do you find any differences between what you will have and the
 following I had?

I could see the same output with your latest script, also I could reproduce
the test if I run the test with individual sql statements.
One of the main point for reproducing individual test was to keep autovacuum
= off.

Now I can look into it further, I have still not gone through in detail
about your new approach to calculate the reltuples, but I am wondering
whether there can be anyway with which estimates can be improved with
different calculation in vac_estimate_reltuples().

One thing I have observed that 2nd parameter is_analyze of
vac_estimate_reltuples() is currently not used.

I cannot work on it till early next week, so others are welcome to join
review.

With Regards,
Amit Kapila.



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-27 Thread Robert Haas
On Thu, Jun 27, 2013 at 7:27 AM, Amit Kapila amit.kap...@huawei.com wrote:
 Now I can look into it further, I have still not gone through in detail
 about your new approach to calculate the reltuples, but I am wondering
 whether there can be anyway with which estimates can be improved with
 different calculation in vac_estimate_reltuples().

I think this is getting at the threshold question for this patch,
which is whether it's really making things better or just moving the
problems around.  I mean, I have no problem accepting that the new
algorithm is (1) reasonably cheap and (2) better in some cases.  But
if it's worse in other cases, which AFAICS hasn't been discussed, then
it's no good.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-25 Thread Kyotaro HORIGUCHI
Hello, 

 I have tried to reproduce the problem in different m/c's, but couldn't
 reproduce it.
 I have ran tests with default configuration.

I think you had reproduced it.

 Output on Windows:
 ---
 postgres=# create table t (a int, b int); 
(snip)
 postgres=# select n_live_tup, n_dead_tup from pg_stat_user_tables where
 relname= 
 't'; 
  n_live_tup | n_dead_tup 
 + 
   10001 | 98 
 (1 row)

Yes, this is the same for me. You should've done this instead,

postgres=# select reltuples from pg_class where relname = 't';
 reltuples 
---
 1e+06
(1 row)

This is 100 times larger than n_live_tup, and it is this value
which used for judge the necessity of autovacuum.

autovacuum.c: 2695
|   reltuples = classForm-reltuples;
|   vactuples = tabentry-n_dead_tuples;
   
|   vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
|   anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;

Although..

 Output on Suse
 
 postgres=# drop table if exists t; 
 create table t (a int, b int); 
 insert into t (select a, (random() * 10)::int from
 generate_series((select count(*) from t) + 1, 100) a); 
 update t set b = b + 1 where a   (select count(*) from t) * 0.7; 
 vacuum t; 
 delete from t where a  (select count(*) from t) * 0.99; 
 vacuum t; 
 select c.relpages, s.n_live_tup, c.reltuples, (select count(*) from t) as
 tuples, reltuples::float / (select count(*) from t) as ratio  from
 pg_stat_user_tables s, pg_class c where s.relname = 't' and c.relname =
 't';DROP TABLE 
 postgres=# CREATE TABLE 
 postgres=# INSERT 0 100 
 postgres=# UPDATE 69 
 postgres=# VACUUM 
 postgres=# DELETE 98 
 postgres=# VACUUM 
 postgres=# 
  relpages | n_live_tup | reltuples | tuples | ratio 
 --++---++--- 
  4425 |  10001 | 10001 |  10001 | 1 
 (1 row)

... Mmm.. I have following figures for the same operation.


 relpages | n_live_tup | reltuples | tuples |  ratio   
--++---++--
 4425 | 417670 |417670 |  10001 | 41.7628237176282

I condisider on this for a time..

 When I tried to run vactest.sh, it gives below error:
 linux:~/akapila/vacuum_nlivetup ./vactest.sh 
 ./vactest.sh: line 11: syntax error near unexpected token `' 
 ./vactest.sh: line 11: `psql ${dbname} -c vacuum verbose t |
 egrep INFO: *\t\: found  | sed -e 's/^.* versions in \([0-9]*\)
 .*$/\1/''
 
 
 Can you help me in reproducing the problem by letting me know if I am doing
 something wrong or results of test are not predictable?

Could you let me know the pg's version you're running?  And it is
appreciated if you're kindly show me the vacuum logs while
testing.

# I found a silly bug in the patch, but I put it off.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-25 Thread Kyotaro HORIGUCHI
Sorry for lots of mistakes I've made,

I noticed that I was dancing on the 9.3dev at sometime, so I
reran on 9.4devel up to date, having the same result from the
view of inaccuracy of pg_class.reltuples after vacuuming.

Although, what differs from my old testset, vacuum reported that
it sanned the whole table pages. It cannot be the case that it
gives such a reltuples value for the case since before...

Please let me have a bit of time to diagnose this. 

=
 When I tried to run vactest.sh, it gives below error:
 linux:~/akapila/vacuum_nlivetup ./vactest.sh 
 ./vactest.sh: line 11: syntax error near unexpected token `' 
 ./vactest.sh: line 11: `psql ${dbname} -c vacuum verbose t |
 egrep INFO: *\t\: found  | sed -e 's/^.* versions in \([0-9]*\)
 .*$/\1/''

'|' I carelessly used should not be understood by real
/bin/sh. Since I might use other notations out of sh syntex, it
seems to more helpful to replace the shbang with '/bin/bash'
instead of '/bin/sh'..

In addition, the test script I brought up here discards all
outputs of sql commands. The attached script shows the verbose
response from vacuum.

 - replaced shbang with /bin/bash
 - replaced '|' notation with '21 |'
 - removed ' /dev/null' from psql commandline

 Can you help me in reproducing the problem by letting me know
 if I am doing something wrong or results of test are not
 predictable?

Thank you for getting involved and sorry for the insufficient
preparation. But please wait for a while to go on.

I ran the attached revised script for the distcleaned current
head on the master branch (9.4devel) on CentOS 6.4 and got the
same result as previous, shown below. But I found the result
ununderstandable. I'd like to have a bit time to diagnose this.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center


===
$ ./vactest.sh
test1 ratio = 0.4
DROP TABLE
CREATE TABLE
INSERT 0 100
UPDATE 69
psql:stdin:5: INFO:  vacuuming public.t
psql:stdin:5: INFO:  t: removed 69 row versions in 4459 pages
psql:stdin:5: INFO:  t: found 69 removable, 100 nonremovable row 
versions in 10829 out of 10829 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.13u sec elapsed 0.13 sec.
VACUUM
DELETE 39
test1 ratio = 0.99
DROP TABLE
CREATE TABLE
INSERT 0 100
UPDATE 69
psql:stdin:5: INFO:  vacuuming public.t
psql:stdin:5: INFO:  t: removed 69 row versions in 4459 pages
psql:stdin:5: INFO:  t: found 69 removable, 100 nonremovable row 
versions in 10829 out of 10829 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.15u sec elapsed 0.25 sec.
VACUUM
DELETE 98
test1 ratio = 1.00
DROP TABLE
CREATE TABLE
INSERT 0 100
UPDATE 69
psql:stdin:5: INFO:  vacuuming public.t
psql:stdin:5: INFO:  t: removed 69 row versions in 4459 pages
psql:stdin:5: INFO:  t: found 69 removable, 100 nonremovable row 
versions in 10829 out of 10829 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.14u sec elapsed 0.19 sec.
VACUUM
DELETE 99
 # | del% | ## | pages | n_live_tup | tups est | tups real |  est/real  | bufs 
---+--++---++--+---++--
 1 |  0.4 |  1 | 10829 | 61 |   764808 |61 |  1.275 | 2549
 1 | 0.99 |  1 |  6370 |  10001 |   417600 | 10001 | 41.756 | 6308
 1 |1 |  1 |  6370 |  1 |   411673 | 1 | 411673.000 | 6371
(3 rows)

#! /bin/bash

dbname=postgres
function insert_result() {
psql ${dbname} -f -  /dev/null EOF
insert into result select $1, $2, $3, c.relpages, s.n_live_tup, c.reltuples, 
(select count(*) from t), reltuples::float / (select count(*) from t) from 
pg_stat_user_tables s, pg_class c where s.relname = 't' and c.relname = 't';
EOF
}

function vac_with_bufs() {
psql ${dbname} -c vacuum verbose t 21 |  egrep INFO: *\t\: found 
 | sed -e 's/^.* versions in \([0-9]*\) .*$/\1/'
}

function update_result_bufs() {
local test_no=$1
local delratio=$2
local vac_no=$3
local bufs=$4

psql ${dbname} -c update result set bufs=${bufs} where \#\=$test_no 
and \del%\=$delratio and \##\=$vac_no /dev/null
}

function store_result() {
local test_no=$1
local delratio=$2
scanned_bufs=`vac_with_bufs`
insert_result $test_no $delratio 1
update_result_bufs $test_no $delratio 1 $scanned_bufs
#   scanned_bufs=`vac_with_bufs`
#   insert_result $test_no $delratio 2
#   update_result_bufs $test_no $delratio 2 $scanned_bufs
}


function test1() {
local delratio=$1

echo test1 ratio = $delratio
psql ${dbname} -f - EOF
drop table if exists t;
create table t (a int, b int, c int, d int default 0, e int default 0, f int 
default 0);

Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-25 Thread Kyotaro HORIGUCHI
I've recovered from messing up.

snip
 Please let me have a bit of time to diagnose this. 

I was completely messed up and walking on the wrong way. I looked
into the vacuum for UPDATEs, not DELETE's so it's quite resonable
to have such results.

The renewed test script attached shows the verbose output of
vacuum after the deletes. I had following output from it.

# I belive this runs for you..

| INFO: t: found 98 removable, 110 nonremovable row
|   versions in 6308 out of 10829 pages

On such a case of partially-scanned, lazy_scan_heap() tries to
estimate resulting num_tuples in vac_estimate_reltuples()
assuming the uniformity of tuple density, which failes for such a
a strong imbalance made by bulk updates.

Do you find any differences between what you will have and the
following I had?

| $ ./vactest.sh
| ### test1 ratio = 0.4
| INFO:  vacuuming public.t
| INFO:  t: removed 39 row versions in 2549 pages
| INFO:  t: found 39 removable, 194 nonremovable row versions in 2549 out 
of 10829 pages
| DETAIL:  0 dead row versions cannot be removed yet.
| There were 0 unused item pointers.
| 0 pages are entirely empty.
| CPU 0.00s/0.04u sec elapsed 0.04 sec.
| ### test1 ratio = 0.99
| INFO:  vacuuming public.t
| INFO:  t: removed 98 row versions in 6308 pages
| INFO:  t: found 98 removable, 110 nonremovable row versions in 6308 out 
of 10829 pages
| DETAIL:  0 dead row versions cannot be removed yet.
| There were 93 unused item pointers.
| 0 pages are entirely empty.
| CPU 0.00s/0.11u sec elapsed 0.24 sec.
| INFO:  t: truncated 10829 to 6370 pages
| DETAIL:  CPU 0.00s/0.00u sec elapsed 0.01 sec.
| ### test1 ratio = 1.00
| INFO:  vacuuming public.t
| INFO:  t: removed 99 row versions in 6371 pages
| INFO:  t: found 99 removable, 1 nonremovable row versions in 6371 out 
of 10829 pages
| DETAIL:  0 dead row versions cannot be removed yet.
| There were 93 unused item pointers.
| 0 pages are entirely empty.
| CPU 0.00s/0.11u sec elapsed 0.20 sec.
| INFO:  t: truncated 10829 to 6370 pages
| DETAIL:  CPU 0.01s/0.00u sec elapsed 0.27 sec.
|  # | del% | ## | pages | n_live_tup | tups est | tups real |  est/real  | 
bufs 
| 
---+--++---++--+---++--
|  1 |  0.4 |  1 | 10829 | 61 |   764808 |61 |  1.275 | 2549
|  1 | 0.99 |  1 |  6370 |  10001 |   417600 | 10001 | 41.756 | 6308
|  1 |1 |  1 |  6370 | 411673 |   411673 | 1 | 411673.000 | 6371
| (3 rows)

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
#! /bin/bash

dbname=postgres
function insert_result() {
psql ${dbname} -f -  /dev/null EOF
insert into result select $1, $2, $3, c.relpages, s.n_live_tup, c.reltuples, 
(select count(*) from t), reltuples::float / (select count(*) from t) from 
pg_stat_user_tables s, pg_class c where s.relname = 't' and c.relname = 't';
EOF
}

function vac_with_bufs() {
local f=`mktemp vactest_`
psql ${dbname} -c vacuum verbose t 2$f 1/dev/null
cat $f 12
cat $f | egrep INFO: *\t\: found  | sed -e 's/^.* versions in 
\([0-9]*\) .*$/\1/'
rm $f
}

function update_result_bufs() {
local test_no=$1
local delratio=$2
local vac_no=$3
local bufs=$4

psql ${dbname} -c update result set bufs=${bufs} where \#\=$test_no 
and \del%\=$delratio and \##\=$vac_no /dev/null
}

function store_result() {
local test_no=$1
local delratio=$2
scanned_bufs=`vac_with_bufs`
insert_result $test_no $delratio 1
update_result_bufs $test_no $delratio 1 $scanned_bufs
#   scanned_bufs=`vac_with_bufs`
#   insert_result $test_no $delratio 2
#   update_result_bufs $test_no $delratio 2 $scanned_bufs
}


function test1() {
local delratio=$1

echo ### test1 ratio = $delratio
psql ${dbname} -f -  /dev/null EOF
drop table if exists t;
create table t (a int, b int, c int, d int default 0, e int default 0, f int 
default 0);
insert into t (select a, (random() * 10)::int from generate_series((select 
count(*) from t) + 1, $nrows) a);
update t set b = b + 1 where a   (select count(*) from t) * 0.7;
vacuum t;
delete from t where a  (select count(*) from t) * $delratio
EOF
store_result 1 $delratio
}

function test2() {
local delratio=$1

echo ### test2 ratio = $delratio
psql ${dbname} -f -  /dev/null EOF
drop table if exists t;
create table t (a int, b text);
insert into t (select a, 'abcdefg' from generate_series((select count(*) from 
t) + 1, $nrows) a);
update t set b = repeat('abcdefghij', 250) where a   (select count(*) from t) 
* 0.7;
vacuum t;
delete from t where a  (select count(*) from t) * $delratio;
EOF
store_result 2 $delratio
}

psql ${dbname} -f -  /dev/null EOF
drop table if exists result;
create table result (# int, del% float, ## int, pages int, n_live_tup 
int, tups est int, tups real int, est/real numeric(10, 3), 

Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-25 Thread Amit Kapila
On Tuesday, June 25, 2013 2:06 PM Kyotaro HORIGUCHI wrote:
 Hello,
 
  I have tried to reproduce the problem in different m/c's, but
 couldn't
  reproduce it.
  I have ran tests with default configuration.
 
 I think you had reproduced it.
 
  Output on Windows:
  ---
  postgres=# create table t (a int, b int);
 (snip)
  postgres=# select n_live_tup, n_dead_tup from pg_stat_user_tables
 where
  relname=
  't';
   n_live_tup | n_dead_tup
  +
10001 | 98
  (1 row)
 
 Yes, this is the same for me. You should've done this instead,
 
 postgres=# select reltuples from pg_class where relname = 't';
  reltuples
 ---
  1e+06
 (1 row)
 
 This is 100 times larger than n_live_tup, and it is this value
 which used for judge the necessity of autovacuum.
 
 autovacuum.c: 2695
 |   reltuples = classForm-reltuples;
 |   vactuples = tabentry-n_dead_tuples;
 
 |   vacthresh = (float4) vac_base_thresh + vac_scale_factor *
 reltuples;
 |   anlthresh = (float4) anl_base_thresh + anl_scale_factor *
 reltuples;
 
 Although..
 
  Output on Suse
  
  postgres=# drop table if exists t;
  create table t (a int, b int);
  insert into t (select a, (random() * 10)::int from
  generate_series((select count(*) from t) + 1, 100) a);
  update t set b = b + 1 where a   (select count(*) from t) * 0.7;
  vacuum t;
  delete from t where a  (select count(*) from t) * 0.99;
  vacuum t;
  select c.relpages, s.n_live_tup, c.reltuples, (select count(*) from
 t) as
  tuples, reltuples::float / (select count(*) from t) as ratio  from
  pg_stat_user_tables s, pg_class c where s.relname = 't' and c.relname
 =
  't';DROP TABLE
  postgres=# CREATE TABLE
  postgres=# INSERT 0 100
  postgres=# UPDATE 69
  postgres=# VACUUM
  postgres=# DELETE 98
  postgres=# VACUUM
  postgres=#
   relpages | n_live_tup | reltuples | tuples | ratio
  --++---++---
   4425 |  10001 | 10001 |  10001 | 1
  (1 row)
 
 ... Mmm.. I have following figures for the same operation.
 
 
  relpages | n_live_tup | reltuples | tuples |  ratio
 --++---++--
  4425 | 417670 |417670 |  10001 | 41.7628237176282
 
 I condisider on this for a time..
 
  When I tried to run vactest.sh, it gives below error:
  linux:~/akapila/vacuum_nlivetup ./vactest.sh
  ./vactest.sh: line 11: syntax error near unexpected token `'
  ./vactest.sh: line 11: `psql ${dbname} -c vacuum verbose t
 |
  egrep INFO: *\t\: found  | sed -e 's/^.* versions in \([0-9]*\)
  .*$/\1/''
 
 
  Can you help me in reproducing the problem by letting me know if I am
 doing
  something wrong or results of test are not predictable?
 
 Could you let me know the pg's version you're running? 

I had used 9.4 Head to run above tests.
Sorry, yesterday I was busy with some other work so could not got time to
check and work on this issue further.
I shall try to work on it today.

 And it is
 appreciated if you're kindly show me the vacuum logs while
 testing.
 
 # I found a silly bug in the patch, but I put it off.
 
 regards,
 
 --
 Kyotaro Horiguchi
 NTT Open Source Software Center



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-24 Thread Amit Kapila
On Friday, June 14, 2013 2:05 PM Kyotaro HORIGUCHI wrote:
 Hello,
 
 Postgresql estimates the number of live tuples after the vacuum has
 left some buffers unscanned. This estimation does well for most cases,
 but makes completely different result with a strong imbalance of tuple
 density.
 
 For example,
 
 create table t (a int, b int);
 insert into t (select a, (random() * 10)::int from
 generate_series((select count(*) from t) + 1, 100) a); update t set
 b = b + 1 where a   (select count(*) from t) * 0.7; vacuum t; delete
 from t where a  (select count(*) from t) * 0.99;
 
 After this, pg_stat_user_tables.n_live_tup shows 417670 which is
 41 times larger than the real number of rows 11. 
  Number should be 10001 not 11.

 And what makes it
 worse, autovacuum nor autoanalyze won't run until n_dead_tup goes above
 8 times larger than the real number of tuples in the table for the
 default settings..
 
 
 | postgres=# select n_live_tup, n_dead_tup
 |from pg_stat_user_tables where relname='t';  n_live_tup |
 | n_dead_tup
 | +
 |  417670 |  0
 |
 | postgres=# select reltuples from pg_class where relname='t';
 | reltuples
 | ---
 | 417670
 |
 | postgres=# select count(*) from t;
 |  count
 | ---
 |  10001

I have tried to reproduce the problem in different m/c's, but couldn't
reproduce it.
I have ran tests with default configuration.

Output on Windows:
---
postgres=# create table t (a int, b int); 
CREATE TABLE 
postgres=# insert into t (select a, (random() * 10)::int from
generate_serie 
s((select count(*) from t) + 1, 100) a); 
INSERT 0 100 
postgres=# update t set b = b + 1 where a   (select count(*) from t) * 0.7;

UPDATE 69 
postgres=# vacuum t; 
VACUUM 
postgres=# delete from t where a  (select count(*) from t) * 0.99; 
DELETE 98 
postgres=# 
postgres=# select n_live_tup, n_dead_tup from pg_stat_user_tables where
relname= 
't'; 
 n_live_tup | n_dead_tup 
+ 
  10001 | 98 
(1 row)


Output on Suse

postgres=# drop table if exists t; 
create table t (a int, b int); 
insert into t (select a, (random() * 10)::int from
generate_series((select count(*) from t) + 1, 100) a); 
update t set b = b + 1 where a   (select count(*) from t) * 0.7; 
vacuum t; 
delete from t where a  (select count(*) from t) * 0.99; 
vacuum t; 
select c.relpages, s.n_live_tup, c.reltuples, (select count(*) from t) as
tuples, reltuples::float / (select count(*) from t) as ratio  from
pg_stat_user_tables s, pg_class c where s.relname = 't' and c.relname =
't';DROP TABLE 
postgres=# CREATE TABLE 
postgres=# INSERT 0 100 
postgres=# UPDATE 69 
postgres=# VACUUM 
postgres=# DELETE 98 
postgres=# VACUUM 
postgres=# 
 relpages | n_live_tup | reltuples | tuples | ratio 
--++---++--- 
 4425 |  10001 | 10001 |  10001 | 1 
(1 row)


When I tried to run vactest.sh, it gives below error:
linux:~/akapila/vacuum_nlivetup ./vactest.sh 
./vactest.sh: line 11: syntax error near unexpected token `' 
./vactest.sh: line 11: `psql ${dbname} -c vacuum verbose t |
egrep INFO: *\t\: found  | sed -e 's/^.* versions in \([0-9]*\)
.*$/\1/''


Can you help me in reproducing the problem by letting me know if I am doing
something wrong or results of test are not predictable?

With Regards,
Amit Kapila.



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] Reduce maximum error in tuples estimation after vacuum.

2013-06-14 Thread Kyotaro HORIGUCHI
Sorry, I made an mistake.

Kyotaro HORIGUCHI horiguchi.kyot...@lab.ntt.co.jp:

 Overall algorithm could be illistrated as below,

  - summing up used bytes, max offnum(PageGetMaxOffsetNumber),

Not max offnum, the number of linp's used after page vacuum.

maximum free bytes for tuple data , and free bytes after page
vacuum through all scanned pages.

  - summing up free bytes informed by FSM through all skipped
pages.

  - Calculate mean tuple length from the overall used bytes and
sum of max offnums, and scanned pages.

Here also is the same. not sum of max offnum but total of used
entrre(linp)s.

  - Guess tuple density in skipped pages using overall free bytes
from FSM and the mean tuple length calculated above.

  - Finally, feed estimated number of the live tuples BEFORE
vacuum into vac_estimate_reltuples.

regards,

-- 
Kyotaro Horiguchi