Understanding EXPLAIN ANALYZE output

Started by Ed L.about 21 years ago51 messagesgeneral
Jump to latest
#1Ed L.
pgsql@bluepolka.net

I'm trying to optimize a large query by looking at
EXPLAIN ANALYZE output. Here's what I think may be
the most relevant snippet:

21 -> Nested Loop (cost=0.00..108.85 rows=1 width=1196) (actual time=4769.59..4769.59 rows=0 loops=1)
22 -> Nested Loop (cost=0.00..64.78 rows=4 width=131) (actual time=0.41..72.80 rows=1014 loops=1)
23 -> Nested Loop (cost=0.00..40.68 rows=4 width=103) (actual time=0.34..46.51 rows=1014 loops=1)
24 -> Nested Loop (cost=0.00..32.40 rows=3 width=52) (actual time=0.24..11.07 rows=689 loops=1)
25 -> Index Scan using uc_review_reviewnum on review (cost=0.00..3.85 rows=1 width=28) (actual time=0.12..0.13 rows=1 loops=1)
26 Index Cond: (reviewnum = '1890382'::bpchar)
27 -> Index Scan using idx_customerorder_review_key on customerorder (cost=0.00..27.90 rows=52 width=24) (actual time=0.11..8.07 rows=689 loops=1)
28 Index Cond: ("outer"."key" = customerorder.review_key)
29 Filter: (ordertype = 'TEST'::bpchar)
30 -> Index Scan using idx_occurrencehistory_customerorder_key on occurrencehistory (cost=0.00..3.05 rows=2 width=51) (actual time=0.02..0.04 rows=1 loops=689)
31 Index Cond: ("outer"."key" = occurrencehistory.customerorder_key)
32 -> Index Scan using pk_user on user (cost=0.00..5.80 rows=1 width=28) (actual time=0.01..0.01 rows=1 loops=1014)
33 Index Cond: ("outer".user_key = user."key")
34 -> Index Scan using idx_queryoutcome_occurrencehistory_key on queryoutcome (cost=0.00..10.28 rows=28 width=1065) (actual time=4.63..4.63 rows=0 loops=1014)
35 Index Cond: ("outer"."key" = queryoutcome.occurrencehistory_key)
36 -> Index Scan using pk_querydefinition on querydefinition (cost=0.00..5.99 rows=1 width=58) (never executed)
37 Index Cond: ("outer".querydefinition_key = querydefinition."key")

If I understand these correctly, line 22's nested loop finished
returning the last row 72.80ms into the query, and then line
21's nested loop returns its 0 rows 4769.59ms into the query.
That would seem to mean 4696.79ms were spent executing the
nested loop on line 21 prior to returning the first row.

If I got that right, how do I figure out what constitutes the
nested loop of line 21?

TIA.

Ed

#2Alvaro Herrera
alvherre@dcc.uchile.cl
In reply to: Ed L. (#1)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 11:00:00AM -0700, Ed L. wrote:

34 -> Index Scan using idx_queryoutcome_occurrencehistory_key on queryoutcome (cost=0.00..10.28 rows=28 width=1065) (actual time=4.63..4.63 rows=0 loops=1014)

^^^^^^^^^^ ^^^^

35 Index Cond: ("outer"."key" = queryoutcome.occurrencehistory_key)

If I understand these correctly, line 22's nested loop finished
returning the last row 72.80ms into the query, and then line
21's nested loop returns its 0 rows 4769.59ms into the query.
That would seem to mean 4696.79ms were spent executing the
nested loop on line 21 prior to returning the first row.

4796.0 ms are the time it took for 34's index scan to complete the 1014
loops, I'd think.

--
Alvaro Herrera (<alvherre[@]dcc.uchile.cl>)
"La naturaleza, tan fr�gil, tan expuesta a la muerte... y tan viva"

#3Alvaro Herrera
alvherre@dcc.uchile.cl
In reply to: Ed L. (#1)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 12:54:27PM -0700, Ed L. wrote:

On Wednesday February 9 2005 12:04, you wrote:

4796.0 ms are the time it took for 34's index scan to complete
the 1014 loops, I'd think.

Interesting. Reindexing the index

idx_queryoutcome_occurrencehistory_key

sped up the query to sub-second. This is a 7.3.4 cluster. I
wonder if this that 7.3 index bloat bug?

Hard to say, because you didn't provide more info (such as if the index
has the right deletion pattern), but it could be.

--
Alvaro Herrera (<alvherre[@]dcc.uchile.cl>)
"I call it GNU/Linux. Except the GNU/ is silent." (Ben Reiter)

#4Ed L.
pgsql@bluepolka.net
In reply to: Alvaro Herrera (#3)
Re: Understanding EXPLAIN ANALYZE output

On Wednesday February 9 2005 12:56, Alvaro Herrera wrote:

On Wed, Feb 09, 2005 at 12:54:27PM -0700, Ed L. wrote:

sped up the query to sub-second. This is a 7.3.4 cluster.
I wonder if this that 7.3 index bloat bug?

Hard to say, because you didn't provide more info (such as if
the index has the right deletion pattern), but it could be.

What delete pattern would cause the problem?

Ed

#5Alvaro Herrera
alvherre@dcc.uchile.cl
In reply to: Ed L. (#4)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 01:11:36PM -0700, Ed L. wrote:

On Wednesday February 9 2005 12:56, Alvaro Herrera wrote:

On Wed, Feb 09, 2005 at 12:54:27PM -0700, Ed L. wrote:

sped up the query to sub-second. This is a 7.3.4 cluster.
I wonder if this that 7.3 index bloat bug?

Hard to say, because you didn't provide more info (such as if
the index has the right deletion pattern), but it could be.

What delete pattern would cause the problem?

A key on which you insert on one side and delete on the other. A table
indexed by date, and you regularly delete the oldest entries, for
example.

--
Alvaro Herrera (<alvherre[@]dcc.uchile.cl>)
"El Maquinismo fue proscrito so pena de cosquilleo hasta la muerte"
(Ijon Tichy en Viajes, Stanislaw Lem)

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ed L. (#1)
Re: Understanding EXPLAIN ANALYZE output

"Ed L." <pgsql@bluepolka.net> writes:

I'm trying to optimize a large query by looking at
EXPLAIN ANALYZE output. Here's what I think may be
the most relevant snippet:

21 -> Nested Loop (cost=0.00..108.85 rows=1 width=1196) (actual time=4769.59..4769.59 rows=0 loops=1)
22 -> Nested Loop (cost=0.00..64.78 rows=4 width=131) (actual time=0.41..72.80 rows=1014 loops=1)
...
34 -> Index Scan using idx_queryoutcome_occurrencehistory_key on queryoutcome (cost=0.00..10.28 rows=28 width=1065) (actual time=4.63..4.63 rows=0 loops=1014)
35 Index Cond: ("outer"."key" = queryoutcome.occurrencehistory_key)

If I understand these correctly, line 22's nested loop finished
returning the last row 72.80ms into the query, and then line
21's nested loop returns its 0 rows 4769.59ms into the query.

No, you don't understand correctly. The numbers are not "time into the
query", they are "elapsed time spent within this node and its
children". The above says that we spent a total of 72.80 msec executing
line 22 and its children, and a total of 4.63*1014 msec executing line
34 (which has no children, so that's all in the indexscan). That adds
up to 4767.62 msec, so the actual joining at line 21 took only 1.97 msec.
None of this tells you anything about how far "into the query" all this
stuff happened. It is however clear that line 34 is the bulk of the
time.

regards, tom lane

#7Ed L.
pgsql@bluepolka.net
In reply to: Tom Lane (#6)
Re: Understanding EXPLAIN ANALYZE output

On Wednesday February 9 2005 2:21, Tom Lane wrote:

"Ed L." <pgsql@bluepolka.net> writes:

21 -> Nested Loop (cost=0.00..108.85 rows=1
width=1196) (actual time=4769.59..4769.59 rows=0 loops=1) 22
-> Nested Loop (cost=0.00..64.78 rows=4 width=131)
(actual time=0.41..72.80 rows=1014 loops=1) ...
34 -> Index Scan using
idx_queryoutcome_occurrencehistory_key on queryoutcome
(cost=0.00..10.28 rows=28 width=1065) (actual
time=4.63..4.63 rows=0 loops=1014) 35 Index
Cond: ("outer"."key" = queryoutcome.occurrencehistory_key)

If I understand these correctly, line 22's nested loop
finished returning the last row 72.80ms into the query, and
then line 21's nested loop returns its 0 rows 4769.59ms into
the query.

No, you don't understand correctly. The numbers are not "time
into the query", they are "elapsed time spent within this node
and its children". The above says that we spent a total of
72.80 msec executing line 22 and its children, and a total of
4.63*1014 msec executing line 34 (which has no children, so
that's all in the indexscan). That adds up to 4767.62 msec,
so the actual joining at line 21 took only 1.97 msec. None of
this tells you anything about how far "into the query" all
this stuff happened. It is however clear that line 34 is the
bulk of the time.

Very helpful, thanks. So time spent in that node & its children
= first number of "actual time" * loops? That seems consistent
with the fact that reindexing the index led to the huge speedup.
If the second number of the "actual time" part means time
elapsed in this node and its children until the last row was
returned, why does it say "actual time=4.63..4.63" instead of
"actual time=4.63..4767.62"? Would it say that if there had
been 1 row returned instead of none?

Ed

#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ed L. (#7)
Re: Understanding EXPLAIN ANALYZE output

"Ed L." <pgsql@bluepolka.net> writes:

If the second number of the "actual time" part means time
elapsed in this node and its children until the last row was
returned, why does it say "actual time=4.63..4.63" instead of
"actual time=4.63..4767.62"?

The reason we do that is to make the "actual" numbers comparable to the
way that the estimated costs are presented. The estimated costs are for
a single execution of the node, but the inner side of a nestloop join is
re-executed for each row coming from the outer side. In this case, the
outer side produced 1014 rows so we ran 1014 separate executions of the
inner indexscan. If we just reported 4767.62 as the total time, it
would look like the estimated indexscan cost of 10.28 was completely out
of whack, which it isn't. So instead, we report a per-execution cost
and a "loops" number that you have to multiply by if you are thinking
about total time spent.

regards, tom lane

#9Martijn van Oosterhout
kleptog@svana.org
In reply to: Ed L. (#7)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 02:37:39PM -0700, Ed L. wrote:

Very helpful, thanks. So time spent in that node & its children
= first number of "actual time" * loops? That seems consistent
with the fact that reindexing the index led to the huge speedup.
If the second number of the "actual time" part means time
elapsed in this node and its children until the last row was
returned, why does it say "actual time=4.63..4.63" instead of
"actual time=4.63..4767.62"? Would it say that if there had
been 1 row returned instead of none?

The meaning of the times is (IIRC) derived from the numbers used in the
planning. The first number is "time to first result", the second number
is "time to last result". So if you're doing a "LIMIT 1" query, only
the first number is relevent.

The purpose of the explain output is to determine where the bottlenecks
are and as such each node only counts time spent in it and all its
subnodes. So for example a Sort node has a really high start time
(because all subnodes must complete before sorting can complete) but
the end time is shortly after because it only needs to pump out tuples.

The complication comes because nodes can be executed in their entirety
repeatedly, especially with nested joins, the inner loop is repeatedly
executed with different parameters. I was one of the major contributers
of this feature originally and there was discussion about how to
represent this. I think the rationale is that the figures should not
appear radically different just because a Node is reexecuted a lot, so
you get an extra result "loops" and the numbers look like a single
index scan. If you look at the numbers the planner uses, it follows the
same pattern.

In general, the EXPLAIN ANALYZE output follows the planner output as
close as possible. If you look at the original query posted, it showed
an Index Scan costing 4.63..4.63 which means the index scan is taking
(on average) 4.63ms to return 1 row! If it displayed as 4000 or
something it would be a lot less clear what was going on.

Hope this helps,
--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/

Show quoted text

Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
tool for doing 5% of the work and then sitting around waiting for someone
else to do the other 95% so you can sue them.

#10Ed L.
pgsql@bluepolka.net
In reply to: Martijn van Oosterhout (#9)
Re: Understanding EXPLAIN ANALYZE output

On Wednesday February 9 2005 3:13, Martijn van Oosterhout wrote:

In general, the EXPLAIN ANALYZE output follows the planner
output as close as possible. If you look at the original query
posted, it showed an Index Scan costing 4.63..4.63 which means
the index scan is taking (on average) 4.63ms to return 1 row!
If it displayed as 4000 or something it would be a lot less
clear what was going on.

Hope this helps,

Both replies help very much, thanks. Regarding 4.63ms to return
a row, I know I/O speeds vary widely depending on conditions and
hardware, but what would you say is a "red flag" value for the
actual time to retrieve a row. I see that for most of the other
times in this example, 0.01ms to 0.10ms is not unusual.

Ed

#11Martijn van Oosterhout
kleptog@svana.org
In reply to: Ed L. (#10)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 03:38:32PM -0700, Ed L. wrote:

On Wednesday February 9 2005 3:13, Martijn van Oosterhout wrote:

In general, the EXPLAIN ANALYZE output follows the planner
output as close as possible. If you look at the original query
posted, it showed an Index Scan costing 4.63..4.63 which means
the index scan is taking (on average) 4.63ms to return 1 row!
If it displayed as 4000 or something it would be a lot less
clear what was going on.

Hope this helps,

Both replies help very much, thanks. Regarding 4.63ms to return
a row, I know I/O speeds vary widely depending on conditions and
hardware, but what would you say is a "red flag" value for the
actual time to retrieve a row. I see that for most of the other
times in this example, 0.01ms to 0.10ms is not unusual.

That number 4.63ms is way out. Especially considering this is an
*average* over 1000+ iterations which tells you something it very wrong
with that step. Note, Index Scan can take a long time, it completely
depends on how many rows it returns. Also, if there is an additional
filter on the index (someotherfield = 'x') it may take a while to
return a single value.

But for unique indexes on primary keys (which is what this appears to
be) the times should hopefully be <1ms *average* (caching and load are
imprtant factors).

Hope this helps,
--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/

Show quoted text

Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
tool for doing 5% of the work and then sitting around waiting for someone
else to do the other 95% so you can sue them.

#12Ed L.
pgsql@bluepolka.net
In reply to: Ed L. (#10)
Re: Understanding EXPLAIN ANALYZE output

Thinking about how to make this analysis faster and less labor-
intensive ...

I know of no other way to get the detailed performance data provided
via EXPLAIN ANALYZE without just painfully disassembling a query.
It seems it would be pretty useful w/r/t performance monitoring to
be able to retrieve such performance numbers as those in EXPLAIN
ANALYZE in a rowset via query. That would seem to enable automated
identification of things like single rows taking 4.63ms to retrieve.
I can think of a number of application queries for which I would
like to do this sort of analysis routinely across a bunch of
database clusters. I guess one could just parse the explain output
in the meantime but, dreaming a bit here, for example,

SELECT node_id, op, parent_node_id, index, relation,
cost_first, cost_last, cost_rows, cost_width,
actual_first, actual_last, actual_rows, actual_loops,
index_condition
FROM pg_explain_analyze('SELECT * FROM foo');

with output similar to

node_id | op | parent_node_id ... actual_last | actual_rows | actual_loops ...
---------+-------------+----------------...--------------+-------------+--------------...
21 | Nested Loop | 20 ... 72.80 | 1014 | 1
22 | Nested Loop | 21 ... 46.51 | 1014 | 1
...
34 | Index Scan | 21 ... 4.63 | 0 | 1014
...

Then, as a routine measure, catch those cases like this one,

SELECT sql, op, index, relation, actual_first
FROM pg_explain_analyze('SELECT * FROM foo')
WHERE op = 'Index Scan'
AND actual_first > 1.0;

Thankfully, I'm sure there are a lot of skilled postgresql'ers
just sitting around right now wishing they had something to do.

Ed

#13David Fetter
david@fetter.org
In reply to: Ed L. (#12)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 04:34:30PM -0700, Ed L. wrote:

Thinking about how to make this analysis faster and less labor-
intensive ...

I know of no other way to get the detailed performance data provided
via EXPLAIN ANALYZE without just painfully disassembling a query.
It seems it would be pretty useful w/r/t performance monitoring to
be able to retrieve such performance numbers as those in EXPLAIN
ANALYZE in a rowset via query. That would seem to enable automated
identification of things like single rows taking 4.63ms to retrieve.
I can think of a number of application queries for which I would
like to do this sort of analysis routinely across a bunch of
database clusters. I guess one could just parse the explain output
in the meantime but, dreaming a bit here, for example,

SELECT node_id, op, parent_node_id, index, relation,
cost_first, cost_last, cost_rows, cost_width,
actual_first, actual_last, actual_rows, actual_loops,
index_condition
FROM pg_explain_analyze('SELECT * FROM foo');

with output similar to

node_id | op | parent_node_id ... actual_last | actual_rows | actual_loops ...
---------+-------------+----------------...--------------+-------------+--------------...
21 | Nested Loop | 20 ... 72.80 | 1014 | 1
22 | Nested Loop | 21 ... 46.51 | 1014 | 1
...
34 | Index Scan | 21 ... 4.63 | 0 | 1014
...

Then, as a routine measure, catch those cases like this one,

SELECT sql, op, index, relation, actual_first
FROM pg_explain_analyze('SELECT * FROM foo')
WHERE op = 'Index Scan'
AND actual_first > 1.0;

Thankfully, I'm sure there are a lot of skilled postgresql'ers
just sitting around right now wishing they had something to do.

Well, I'm a little bored; I've got tomorrow off, and this seems like
it might be doable in the kind of high-level PL/Foo's with which I'm
familiar. What would the returning rowtype for
pg_explain_analyze(TEXT) be?

Cheers,
D
--
David Fetter david@fetter.org http://fetter.org/
phone: +1 510 893 6100 mobile: +1 415 235 3778

Remember to vote!

#14Joshua D. Drake
jd@commandprompt.com
In reply to: David Fetter (#13)
Re: Understanding EXPLAIN ANALYZE output

David Fetter wrote:

On Wed, Feb 09, 2005 at 04:34:30PM -0700, Ed L. wrote:

Thinking about how to make this analysis faster and less labor-
intensive ...

I know of no other way to get the detailed performance data provided
via EXPLAIN ANALYZE without just painfully disassembling a query.
It seems it would be pretty useful w/r/t performance monitoring to
be able to retrieve such performance numbers as those in EXPLAIN
ANALYZE in a rowset via query. That would seem to enable automated
identification of things like single rows taking 4.63ms to retrieve.
I can think of a number of application queries for which I would
like to do this sort of analysis routinely across a bunch of
database clusters. I guess one could just parse the explain output
in the meantime but, dreaming a bit here, for example,

SELECT node_id, op, parent_node_id, index, relation,
cost_first, cost_last, cost_rows, cost_width,
actual_first, actual_last, actual_rows, actual_loops,
index_condition
FROM pg_explain_analyze('SELECT * FROM foo');

with output similar to

node_id | op | parent_node_id ... actual_last | actual_rows | actual_loops ...
---------+-------------+----------------...--------------+-------------+--------------...
21 | Nested Loop | 20 ... 72.80 | 1014 | 1
22 | Nested Loop | 21 ... 46.51 | 1014 | 1
...
34 | Index Scan | 21 ... 4.63 | 0 | 1014
...

Then, as a routine measure, catch those cases like this one,

SELECT sql, op, index, relation, actual_first
FROM pg_explain_analyze('SELECT * FROM foo')
WHERE op = 'Index Scan'
AND actual_first > 1.0;

Thankfully, I'm sure there are a lot of skilled postgresql'ers
just sitting around right now wishing they had something to do.

Well, I'm a little bored; I've got tomorrow off, and this seems like
it might be doable in the kind of high-level PL/Foo's with which I'm
familiar. What would the returning rowtype for
pg_explain_analyze(TEXT) be?

You could return it as formatted text. if you want to make it simple.

J

Cheers,
D

-- 
Command Prompt, Inc., home of Mammoth PostgreSQL - S/ODBC and S/JDBC
Postgresql support, programming shared hosting and dedicated hosting.
+1-503-667-4564 - jd@commandprompt.com - http://www.commandprompt.com
PostgreSQL Replicator -- production quality replication for PostgreSQL
#15Ed L.
pgsql@bluepolka.net
In reply to: David Fetter (#13)
Re: Understanding EXPLAIN ANALYZE output

On Wednesday February 9 2005 7:31, David Fetter wrote:

On Wed, Feb 09, 2005 at 04:34:30PM -0700, Ed L. wrote:

Thinking about how to make this analysis faster and less
labor- intensive ...

SELECT node_id, op, parent_node_id, index, relation,
cost_first, cost_last, cost_rows, cost_width,
actual_first, actual_last, actual_rows,
actual_loops, index_condition
FROM pg_explain_analyze('SELECT * FROM foo');

Thankfully, I'm sure there are a lot of skilled
postgresql'ers just sitting around right now wishing they
had something to do.

Well, I'm a little bored; I've got tomorrow off, and this
seems like it might be doable in the kind of high-level
PL/Foo's with which I'm familiar. What would the returning
rowtype for
pg_explain_analyze(TEXT) be?

LOL. If you're serious, I was thinking of something like this:

node_id integer not null unique
op varchar: "Index Scan"|"Hash Join"|"Seq Scan"|...
parent_node_id integer: node_id of parent node
index varchar: name of index for scan (oid better?)
relation varchar: name of relation for scan (oid better?)
cost_first float: first cost number
cost_last float: second cost number
cost_rows bigint
cost_width integer
actual_first float: time to first row
actual_last float: time to last row
actual_rows bigint
actual_loops bigint
condition varchar: what comes after "Index Cond:"|"Hash Cond:"|...
total_time float: total query time

How's that?

That might be a start. This is half-baked and you may be
the new head chef, so feel free.

Ed

#16Oisin Glynn
me@oisinglynn.com
In reply to: Ed L. (#1)
Functions with more than 32 parameters

Hi,

I am trying to keep database access encapsulated in functions from an insert
and update point of view so as all of the applications writing to the
database are using the same functions/statements.

My problem is I was creating functions to do inserts/updates and now I have
a table with more than 32 columns and the functions seem to only want to
have 32 parameters?

Is there any way around this?

I have used stored procedures in this way with Oracle/SQL server before.Or
is there another strategy I could use?

I am using Windows 2000 Postgres 8.0.1 if it makes a difference

Thanks in advance,
Oisin

#17Ed L.
pgsql@bluepolka.net
In reply to: Ed L. (#15)
Re: Understanding EXPLAIN ANALYZE output

On Wednesday February 9 2005 8:07, Ed L. wrote:

Well, I'm a little bored; I've got tomorrow off, and this
seems like it might be doable in the kind of high-level
PL/Foo's with which I'm familiar. What would the returning
rowtype for
pg_explain_analyze(TEXT) be?

LOL. If you're serious, I was thinking of something like
this:

node_id integer not null unique
op varchar: "Index Scan"|"Hash Join"|"Seq Scan"|...
parent_node_id integer: node_id of parent node
index varchar: name of index for scan (oid better?)
relation varchar: name of relation for scan (oid better?)
cost_first float: first cost number
cost_last float: second cost number
cost_rows bigint
cost_width integer
actual_first float: time to first row
actual_last float: time to last row
actual_rows bigint
actual_loops bigint
condition varchar: what comes after "Index Cond:"|"Hash
Cond:"|... total_time float: total query time

You might drive the rowtype by what you (alias I) hope to get out
of it: 1) easy discovery of the slowest parts of the query, 2)
really slow avg row retrieval times (like the 4.63ms/row
discussed earlier in this thread), and I don't know what else.
Part 2 seems straight forward with this scheme, less sure about
part 1.

Ed

#18Michael Fuhr
mike@fuhr.org
In reply to: David Fetter (#13)
Re: Understanding EXPLAIN ANALYZE output

On Wed, Feb 09, 2005 at 06:31:11PM -0800, David Fetter wrote:

On Wed, Feb 09, 2005 at 04:34:30PM -0700, Ed L. wrote:

SELECT sql, op, index, relation, actual_first
FROM pg_explain_analyze('SELECT * FROM foo')
WHERE op = 'Index Scan'
AND actual_first > 1.0;

Thankfully, I'm sure there are a lot of skilled postgresql'ers
just sitting around right now wishing they had something to do.

Well, I'm a little bored; I've got tomorrow off, and this seems like
it might be doable in the kind of high-level PL/Foo's with which I'm
familiar. What would the returning rowtype for
pg_explain_analyze(TEXT) be?

I started looking at this earlier. Is it even possible to get
EXPLAIN output via SPI (and thus the PLs' interfaces to SPI)? Or
would the function have to make a new connection to the database
and issue the EXPLAIN as an ordinary client? I suppose a proper
implementation would be written in C and would call the internal
functions that generate the output, but I was thinking about how
to do something simple in a higher-level PL.

As for the return type, I was going to look at explain_outNode()
in src/backend/commands/explain.c and get some ideas from there.

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

#19Bruce Momjian
bruce@momjian.us
In reply to: Ed L. (#17)
Re: Understanding EXPLAIN ANALYZE output

"Ed L." <pgsql@bluepolka.net> writes:

and I don't know what else.

How about being able to search for queries where expected rows and actual rows
are far apart.

--
greg

#20Oisin Glynn
me@oisinglynn.com
In reply to: Oisin Glynn (#16)
Re: Functions with more than 32 parameters

Any advice for an opensource newbie running on Windows 2000? How hard is it
to rebuild for windows? Any instructions? What compiler?

Oisin

----- Original Message -----
From: "Bradley D. Snobar" <bradsnobar@netscape.net>
To: ""Oisin Glynn"" <me@oisinglynn.com>
Sent: Wednesday, February 09, 2005 10:40 PM
Subject: RE: [GENERAL] Functions with more than 32 parameters

Show quoted text

I just had the same problem the other day.

Change this file:
..../postgresql-8.0.0/src/include/pg_config_manual.h

#define INDEX_MAX_KEYS 64 /*was 32 */
#define FUNC_MAX_ARGS INDEX_MAX_KEYS

Recompile the server.

make distclean
./configure
make
make install

"Oisin Glynn" <me@oisinglynn.com> wrote:

Hi,

I am trying to keep database access encapsulated in functions from an
insert
and update point of view so as all of the applications writing to the
database are using the same functions/statements.

My problem is I was creating functions to do inserts/updates and now I
have
a table with more than 32 columns and the functions seem to only want to
have 32 parameters?

Is there any way around this?

I have used stored procedures in this way with Oracle/SQL server before.Or
is there another strategy I could use?

I am using Windows 2000 Postgres 8.0.1 if it makes a difference

Thanks in advance,
Oisin

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org

__________________________________________________________________
Switch to Netscape Internet Service.
As low as $9.95 a month -- Sign up today at
http://isp.netscape.com/register

Netscape. Just the Net You Need.

New! Netscape Toolbar for Internet Explorer
Search from anywhere on the Web and block those annoying pop-ups.
Download now at http://channels.netscape.com/ns/search/install.jsp

--
No virus found in this incoming message.
Checked by AVG Anti-Virus.
Version: 7.0.305 / Virus Database: 265.8.6 - Release Date: 2/7/2005

#21Tom Lane
tgl@sss.pgh.pa.us
In reply to: Michael Fuhr (#18)
#22Michael Fuhr
mike@fuhr.org
In reply to: Tom Lane (#21)
#23Chris Browne
cbbrowne@acm.org
In reply to: Ed L. (#1)
#24Ed L.
pgsql@bluepolka.net
In reply to: Michael Fuhr (#22)
#25Michael Fuhr
mike@fuhr.org
In reply to: Ed L. (#24)
#26David Fetter
david@fetter.org
In reply to: Oisin Glynn (#16)
#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Michael Fuhr (#22)
#28David Fetter
david@fetter.org
In reply to: Tom Lane (#27)
#29Michael Fuhr
mike@fuhr.org
In reply to: David Fetter (#26)
#30Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Fetter (#28)
#31Harald Fuchs
hf0722x@protecting.net
In reply to: Ed L. (#1)
#32Michael Fuhr
mike@fuhr.org
In reply to: Tom Lane (#27)
#33Michael Fuhr
mike@fuhr.org
In reply to: Michael Fuhr (#32)
#34Martijn van Oosterhout
kleptog@svana.org
In reply to: Harald Fuchs (#31)
#35Michael Fuhr
mike@fuhr.org
In reply to: Martijn van Oosterhout (#34)
#36David Fetter
david@fetter.org
In reply to: Tom Lane (#30)
#37Tom Lane
tgl@sss.pgh.pa.us
In reply to: Martijn van Oosterhout (#34)
#38Ed L.
pgsql@bluepolka.net
In reply to: David Fetter (#36)
#39Tom Lane
tgl@sss.pgh.pa.us
In reply to: Michael Fuhr (#33)
#40David Fetter
david@fetter.org
In reply to: Tom Lane (#39)
#41Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Fetter (#40)
#42David Fetter
david@fetter.org
In reply to: Tom Lane (#41)
#43Chris Browne
cbbrowne@acm.org
In reply to: Ed L. (#1)
#44Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Fetter (#42)
#45Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#37)
#46Martijn van Oosterhout
kleptog@svana.org
In reply to: Tom Lane (#44)
#47Martijn van Oosterhout
kleptog@svana.org
In reply to: Tom Lane (#37)
#48Harald Fuchs
hf0722x@protecting.net
In reply to: Ed L. (#10)
#49Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#44)
#50Martijn van Oosterhout
kleptog@svana.org
In reply to: Harald Fuchs (#48)
#51Harald Fuchs
hf0722x@protecting.net
In reply to: David Fetter (#13)