Bitmap Heap scan 8.1/8.2
I have to PG servers, one ver. 8.1.9 and the other 8.2.4.
I was checking a query out and found that with the exact same DB (same
data in it) and the same query I get different plans, and significantly
higher time in 8.2:
On 8.1 I get:
test=> explain analyze SELECT * FROM prestamos WHERE biblioteca = 19 AND
vencimiento < now() AND NOT devuelto ORDER BY vencimiento DESC;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=2793.74..2795.82 rows=832 width=20) (actual
time=25.795..25.832 rows=49 loops=1)
Sort Key: vencimiento
-> Bitmap Heap Scan on prestamos (cost=850.43..2753.39 rows=832
width=20) (actual time=20.747..25.529 rows=49 loops=1)
Filter: ((biblioteca = 19) AND (vencimiento < now()) AND (NOT
devuelto))
-> Bitmap Index Scan on prestamos_objetos_devuelto_idx
(cost=0.00..850.43 rows=2200 width=0) (actual time=20.265..20.265
rows=2301 loops=1)
Index Cond: (devuelto = false)
Total runtime: 25.971 ms
(7 filas)
On 8.2:
test=> explain analyze SELECT * FROM prestamos WHERE biblioteca = 19 AND
vencimiento < now() AND NOT devuelto ORDER BY vencimiento DESC;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
Sort (cost=4100.77..4102.77 rows=800 width=20) (actual
time=95.082..95.103 rows=49 loops=1)
Sort Key: vencimiento
-> Seq Scan on prestamos (cost=0.00..4062.20 rows=800 width=20)
(actual time=7.293..82.778 rows=49 loops=1)
Filter: ((biblioteca = 19) AND (vencimiento < now()) AND (NOT
devuelto))
Total runtime: 95.165 ms
(5 filas)
It's like it's ignoring the HEAP scan. Why? It's obviously (unless I'm
totally wrong) faster in this case.
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
Hello
I am unsure, did you check config values?
Pavel
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Show quoted text
I have to PG servers, one ver. 8.1.9 and the other 8.2.4.
I was checking a query out and found that with the exact same DB (same
data in it) and the same query I get different plans, and significantly
higher time in 8.2:On 8.1 I get:
test=> explain analyze SELECT * FROM prestamos WHERE biblioteca = 19 AND
vencimiento < now() AND NOT devuelto ORDER BY vencimiento DESC;QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=2793.74..2795.82 rows=832 width=20) (actual
time=25.795..25.832 rows=49 loops=1)
Sort Key: vencimiento
-> Bitmap Heap Scan on prestamos (cost=850.43..2753.39 rows=832
width=20) (actual time=20.747..25.529 rows=49 loops=1)
Filter: ((biblioteca = 19) AND (vencimiento < now()) AND (NOT
devuelto))
-> Bitmap Index Scan on prestamos_objetos_devuelto_idx
(cost=0.00..850.43 rows=2200 width=0) (actual time=20.265..20.265
rows=2301 loops=1)
Index Cond: (devuelto = false)
Total runtime: 25.971 ms
(7 filas)On 8.2:
test=> explain analyze SELECT * FROM prestamos WHERE biblioteca = 19 AND
vencimiento < now() AND NOT devuelto ORDER BY vencimiento DESC;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
Sort (cost=4100.77..4102.77 rows=800 width=20) (actual
time=95.082..95.103 rows=49 loops=1)
Sort Key: vencimiento
-> Seq Scan on prestamos (cost=0.00..4062.20 rows=800 width=20)
(actual time=7.293..82.778 rows=49 loops=1)
Filter: ((biblioteca = 19) AND (vencimiento < now()) AND (NOT
devuelto))
Total runtime: 95.165 ms
(5 filas)It's like it's ignoring the HEAP scan. Why? It's obviously (unless I'm
totally wrong) faster in this case.--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
------------------------------------------------------------------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set to on.
Anything else?
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set to on.
Anything else?
shared_buffers
work_mem
effective_cache_size
Pavel
Show quoted text
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set to on.
Anything else?
shared_buffers
work_mem
effective_cache_sizePavel
Well, the cost_* values might be interesting too. That is
seq_page_cost
random_page_cost
cpu_tuple_cost
cpu_index_tuple_cost
cpu_operator_cost
effective_cache_size
(the first one is available in 8.2 only). My guess is that there are
different values, and the 8.2 overestimates the index scan - which seems
to be incorrect.
Try to disable the seqscan in the 8.2 database (set enable_seqscan =
off), and run the explain analyze again. This time it should choose
different query plan - maybe the index scan as in 8.1.
Another thing you might try is setting the cost values to the same
values in both databases - it might help.
And what does it mean by 'same data' - have you vacuumed / analyzed both
of them? What does this return:
select relname, relpages, reltuples from pg_class where relname =
'prestamos' or relname='prestamos_objetos_devuelto_idx';
That should return number of tuples / occupied pages in the table and index.
Tomas
Pavel Stehule wrote:
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set to on.
Anything else?
shared_buffers
8.1:
16000
8.2:
400MB
work_mem
8.1:
8192
8.2:
4MB
effective_cache_size
8.1:
1000
8.2:
128MB
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set to on.
Anything else?
shared_buffers
8.1:
16000
~ 128M
8.2:
400MB
work_mem
8.1:
8192
8M !!!! 8>4
8.2:
4MB
effective_cache_size
8.1:
1000
8M
8.2:
128MB
try
set work_mem to '8MB';
and
explain analyze select ..
Tomas Vondra wrote:
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set
to on.Anything else?
shared_buffers
work_mem
effective_cache_sizePavel
Well, the cost_* values might be interesting too. That is
seq_page_cost
random_page_cost
cpu_tuple_cost
cpu_index_tuple_cost
cpu_operator_cost
effective_cache_size(the first one is available in 8.2 only). My guess is that there are
different values, and the 8.2 overestimates the index scan - which seems
to be incorrect.Try to disable the seqscan in the 8.2 database (set enable_seqscan =
off), and run the explain analyze again. This time it should choose
different query plan - maybe the index scan as in 8.1.
siprebi-1.4=> SHOW enable_seqscan ;
enable_seqscan
----------------
off
(1 fila)
siprebi-1.4=> explain analyze SELECT usuarios,nticket,objeto,vencimiento
FROM prestamos WHERE biblioteca = 19 AND vencimiento < now() AND NOT
devuelto ORDER BY vencimiento DESC;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=4365.26..4367.26 rows=800 width=20) (actual
time=30.736..30.755 rows=49 loops=1)
Sort Key: vencimiento
-> Bitmap Heap Scan on prestamos (cost=2502.69..4326.68 rows=800
width=20) (actual time=28.983..30.644 rows=49 loops=1)
Filter: ((biblioteca = 19) AND (vencimiento < now()) AND (NOT
devuelto))
-> Bitmap Index Scan on prestamos_usuarios_devuelto_idx
(cost=0.00..2502.49 rows=1976 width=0) (actual time=28.874..28.874
rows=2300 loops=1)
Index Cond: (devuelto = false)
Total runtime: 45.725 ms
Here I see that the time has been halved. So this plan is much better.
Another thing you might try is setting the cost values to the same
values in both databases - it might help.
Which ones and how?
And what does it mean by 'same data' - have you vacuumed / analyzed both
of them? What does this return:
dumped the 8.1 DB and restored in the 8.2. Both were vacummed analyze to
have accurate stats.
select relname, relpages, reltuples from pg_class where relname =
'prestamos' or relname='prestamos_objetos_devuelto_idx';That should return number of tuples / occupied pages in the table and
index.
select relname, relpages, reltuples from pg_class where relname =
'prestamos' or relname='prestamos_objetos_devuelto_idx';
relname | relpages | reltuples
--------------------------------+----------+-----------
prestamos_objetos_devuelto_idx | 373 | 134697
prestamos | 1705 | 134697
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
Pavel Stehule wrote:
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
2007/10/22, Martin Marques <martin@bugs.unl.edu.ar>:
Pavel Stehule wrote:
Hello
I am unsure, did you check config values?
Don't know which ones you are talking about, but all enable_* are set to on.
Anything else?
shared_buffers
8.1:
16000
~ 128M
8.2:
400MB
work_mem
8.1:
8192
8M !!!! 8>4
8.2:
4MB
effective_cache_size
8.1:
1000
8M
8.2:
128MB
try
set work_mem to '8MB';
and
explain analyze select ..
These things didn't help. What changed the plan completely was this:
seq_page_cost = 5.0 # measured on an arbitrary scale
cpu_tuple_cost = 0.05 # same scale as above
Specially the first one. Now I get this:
explain analyze SELECT usuarios,nticket,objeto,vencimiento FROM
prestamos WHERE biblioteca = 19 AND vencimiento < now() AND NOT
devuelto ORDER BY vencimiento DESC;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=7058.86..7060.86 rows=800 width=20) (actual
time=22.850..22.888 rows=95 loops=1)
Sort Key: vencimiento
-> Index Scan using prestamos_objetos_devuelto_idx on prestamos
(cost=0.00..7020.28 rows=800 width=20) (actual time=0.346..22.590
rows=95 loops=1)
Index Cond: (devuelto = false)
Filter: ((biblioteca = 19) AND (vencimiento < now()) AND (NOT
devuelto))
Total runtime: 22.973 ms
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Martín Marqués | SELECT 'mmarques' ||
Centro de Telemática | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
Martin Marques escribió:
Pavel Stehule wrote:
try
set work_mem to '8MB';
and
explain analyze select ..These things didn't help. What changed the plan completely was this:
seq_page_cost = 5.0 # measured on an arbitrary scale
cpu_tuple_cost = 0.05 # same scale as above
Can someone explain how this parameters are measured? What is 5.0 in
this case for seq_page_cost?
2007/10/23, Martin Marques <martin@bugs.unl.edu.ar>:
Martin Marques escribió:
Pavel Stehule wrote:
try
set work_mem to '8MB';
and
explain analyze select ..These things didn't help. What changed the plan completely was this:
seq_page_cost = 5.0 # measured on an arbitrary scale
cpu_tuple_cost = 0.05 # same scale as aboveCan someone explain how this parameters are measured? What is 5.0 in
this case for seq_page_cost?
http://www.postgresql.org/docs/8.2/interactive/runtime-config-query.html
5.0 means so seq scan will be expensive for optimaliser, and
optimaliser will prefer index scan.
Martin Marques escribi�:
Martin Marques escribi�:
Pavel Stehule wrote:
try
set work_mem to '8MB';
and
explain analyze select ..These things didn't help. What changed the plan completely was this:
seq_page_cost = 5.0 # measured on an arbitrary scale
cpu_tuple_cost = 0.05 # same scale as aboveCan someone explain how this parameters are measured? What is 5.0 in this
case for seq_page_cost?
It's an arbitrary number, based on which all the other numbers are
measured.
What people generally do around here is mess with random_page_cost, and
leave seq_page_cost alone. Often, it's the ratio
seq_page_cost/random_page_cost what's most important to the cost
equations results. (seq_page_cost wasn't tunable at all until
recently, say 8.1 or 8.2 AFAIR).
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Alvaro Herrera <alvherre@commandprompt.com> writes:
Martin Marques escribi�:
seq_page_cost = 5.0 # measured on an arbitrary scale
What people generally do around here is mess with random_page_cost, and
leave seq_page_cost alone.
It's also worth pointing out that having seq_page_cost >
random_page_cost is simply not sane, and is very likely to result in
performance problems in other queries.
regards, tom lane
Alvaro Herrera wrote:
It's an arbitrary number, based on which all the other numbers are
measured.
Now that I read more intensively he docs I see that all the cost
parameters are related one with the other.
What people generally do around here is mess with random_page_cost, and
leave seq_page_cost alone. Often, it's the ratio
seq_page_cost/random_page_cost what's most important to the cost
equations results. (seq_page_cost wasn't tunable at all until
recently, say 8.1 or 8.2 AFAIR).
Ok, now the 8.1 server has a RAID1 hardware board with SCSI disks, and
the 8.2 is just a PentiumD with SATA disks (it's my desktop PC where I
do tests). Should I have a lower random_page_cost on a machine that is
likely to have a lower disk IO speed?
--
21:50:04 up 2 days, 9:07, 0 users, load average: 0.92, 0.37, 0.18
---------------------------------------------------------
Lic. Mart�n Marqu�s | SELECT 'mmarques' ||
Centro de Telem�tica | '@' || 'unl.edu.ar';
Universidad Nacional | DBA, Programador,
del Litoral | Administrador
---------------------------------------------------------
Martin Marques <martin@bugs.unl.edu.ar> writes:
Ok, now the 8.1 server has a RAID1 hardware board with SCSI disks, and
the 8.2 is just a PentiumD with SATA disks (it's my desktop PC where I
do tests). Should I have a lower random_page_cost on a machine that is
likely to have a lower disk IO speed?
I'd guess the other way round: cheaper disks are likely to have worse
seek speeds, which translates to random accesses being proportionally
slower.
regards, tom lane