Re: [HACKERS] statement logging / extended query protocol issues
Bruce Momjian wrote: Simon's page is in the patches queue. What would you like changed, exactly? I'm not going to have time to comment on this any time soon, sorry :( .. I guess I will try to look at it for 8.2. -O ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [HACKERS] statement logging / extended query protocol issues
Oliver Jowett wrote: Bruce Momjian wrote: Well, from the application writer perspective, you are right it doesn't make sense, This is exactly what the end user is going to say. but this is only because jdbc is using prepare internally. Isn't this mostly irrelevant to the result we want to see? It's a detail of how the interface layer chooses to execute its queries, and 90% of the time the end user is not going to know or care about it. Right, but have no way to know if the user is using an interface that hides prepares from them, or they are using prepares visibly in their applications. For this reason, we should just display whatever the backend is doing. If all interfaces used prepares invisibly like jdbc, we would be right to suppress the log information. If you were to have written it in libpq, it would make sense, I think, and internally, this is what is happening. We can't assume only interface libraries like jdbc are using this feature. Wait, so is the extended query protocol the poor cousin of what libpq does, or what? You can do Parse/Bind using libpq, can't you? Sure. The *meaning* of the Parse/Bind/Execute sequence is quite clear regardless of what interface library is used. I still think that logging just the queries that were actually executed, once per execution, is the sensible thing to do here. I can't see a sequence of protocol messages that would produce a strange result if we used the rules I suggested -- do you have an example where it breaks? I have no idea. As far as I understand things, the protocol-level prepare/execute is identical to the SQL-level prepare/execute, except that there is no need to parse the execute, so it should log like the SQL-level statements, if possible. You can Parse any SQL statement, but you can't PREPARE any SQL statement. So, no, they're not equivalent. That's one aspect of what I meant about generating synthetic statements that weren't syntactially correct (the strange FETCH syntax with ROWS/MAXROWS that Simon was suggesting is another case). I am hesitant to add another log syntax to be used just for protocol-level prepare. I think it adds complexity with little benefit, particularly for people reading those logs with automated tools. Simon's page is in the patches queue. What would you like changed, exactly? -- Bruce Momjian| http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup.| Newtown Square, Pennsylvania 19073 ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [HACKERS] statement logging / extended query protocol issues
Your patch has been added to the PostgreSQL unapplied patches list at: http://momjian.postgresql.org/cgi-bin/pgpatches It will be applied as soon as one of the PostgreSQL committers reviews and approves it. --- Simon Riggs wrote: On Thu, 2005-09-08 at 13:14 +1200, Oliver Jowett wrote: Simon Riggs wrote: Oliver, would it be possible to show a simplified call sequence and what you would like to see logged for each call? These are good: Maybe it should even be in the docs for the driver? It would be good if it could be written as a test within the driver, so we can expand it and test the logging. The JDBC driver generates one of these sequences: (1) Parse (unnamed statement) SELECT 1 Bind (unnamed statement - unnamed portal) Execute (unnamed portal, no row limit) (2) Parse (named statement S_1) SELECT 1 repeatedly: Bind (named statement S_1 - unnamed portal) Execute (unnamed portal, no row limit) (3) Parse (named statement S_2) SELECT 1 repeatedly: Bind (named statement S_2 - named portal C_2) repeatedly: Execute (named portal C_2, row limit 42) Are we sure there is just 3 cases? Ideal output is: (1) LOG: statement: SELECT 1 (2) LOG: statement: SELECT 1 LOG: statement: SELECT 1 LOG: statement: SELECT 1 (3) LOG: statement: SELECT 1 LOG: statement: SELECT 1 LOG: statement: SELECT 1 In case (3), that's one log line per repeat of the outer loop, regardless of how many Executes are sent in the inner loop. Note that case (1) is the most common case for application queries via the JDBC driver, and case (2) is the most common for internally generated statements like BEGIN. Even if case (3) is not that common, I still want to know it is occurring, to see what effect or overhead it has. As you can see from the output I'd like, I don't think that synthesizing FETCH / EXECUTE queries that don't actually exist [is a] useful thing to do, at least at the Joe Average User level. Your original point at the top of this thread was valid: a get-next-rows shouldn't look like a re-execute. We can call it something else if you like, as long as we can tell the difference. We'll only see the output for case (3) when someone has programmed things that way by using setFetchSize. Also note that the JDBC driver doesn't exercise all of the extended protocol -- for example it's possible to re-Bind the same unnamed statement repeatedly, or have multiple Executes on an unnamed portal with a row limit, but the JDBC driver never does that. I agree there's not much gained from displaying the BIND statement as it is. I argued previously against including the BIND parameters. Now I would say we should either include them or leave out BIND altogether. Here's a new suggestion and patch that brings together - Oliver and Simon's wish to remove BIND from normal logging - Oliver's suggestion to remove the PREPARE logging for unnamed statements, which would otherwise double-up logging for case(1) - Bruce and Simon's view to keep some form of FETCH logging - Tom's view to rationalise the way ROWS is mentioned (lines beginning jdbc don't show in the log, but are just there to show clearly the time sequence of activities and what gets subsequently logged) (1) Parse (unnamed statement) SELECT * from pg_proc Bind (unnamed statement - unnamed portal) Execute (unnamed portal, no row limit) (1) jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc Notice that the parse of the unnamed statement does *not* now generate a log record. (2) Parse (named statement S_1) SELECT * from pg_proc repeatedly: Bind (named statement S_1 - unnamed portal) Execute (unnamed portal, no row limit) (2) jdbc parse S_1 LOG: statement: PREPARE S_1 AS SELECT * from pg_proc (perhaps this should be logged at BIND time, just like the optimization?) jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] ...I wonder if unnamed just confuses what is going on here? I've left it in for now, but suggest that we take that out again? (3) Parse (named statement S_2) SELECT * from pg_proc repeatedly: Bind (named statement S_2 - named portal C_2) repeatedly: Execute (named portal C_2, row limit 42) (3) jdbc prepare S_2 LOG: statement: PREPARE S_2 AS SELECT * from pg_proc jdbc bind S_2 to C_2
Re: [HACKERS] statement logging / extended query protocol issues
Oliver Jowett wrote: Simon Riggs wrote: Are we sure there is just 3 cases? I haven't exhaustively checked, but I think those are the main cases. Even if case (3) is not that common, I still want to know it is occurring, to see what effect or overhead it has. I don't want it to be more verbose than the other cases when I set log_statement = all. I think it is more verbose because no FETCH is logged in this type of prepare/execute. The goal, I think, is for these type of queries to look as similar to normal PREPARE/EXECUTE and DECLARE/FETCH as possible. We'll only see the output for case (3) when someone has programmed things that way by using setFetchSize. Can we put extra output in this case into log_statement = verbose only please? We don't have a log_statement = verbose mode. (1) jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc Notice that the parse of the unnamed statement does *not* now generate a log record. What about the syntax error case? Good point, but when do we parse? Could you set log_min_error_statement to error? I don't think that would work either. (2) jdbc parse S_1 LOG: statement: PREPARE S_1 AS SELECT * from pg_proc (perhaps this should be logged at BIND time, just like the optimization?) jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] I do not like logging queries that the driver never sent (the driver sends neither PREPARE nor EXECUTE). I also don't see why it's useful to log the statement and portal names. Can we reword this to what I suggested previously? LOG: parse statement: SELECT * from pg_proc LOG: execute statement: SELECT * from pg_proc The problem here is that scripts that look for LOG: statement: would now need to look for additional words at the start. It also makes this type of prepare/execute look different in the logs, while internally it is quite similar. (3) jdbc prepare S_2 LOG: statement: PREPARE S_2 AS SELECT * from pg_proc jdbc bind S_2 to C_2 jdbc execute C_2 LOG: statement: EXECUTE C_2 ROWS 42 [PREPARE: SELECT * from pg_proc] jdbc next (after cache has run out on 42nd row) v3 protocol sends E for Execute, execution halts at 49 rows for this set of bind parameters LOG: statement: FETCH C_2 ROWS 7 Again I do not like logging synthetic queries that the driver never sent (PREPARE / EXECUTE / FETCH). BTW, if you do it this way, you could get the bizarre PREPARE S_2 AS PREPARE xyz AS SELECT .. result if the application used PREPARE itself. I think that logging the second and subsequent Executes is not normally useful and shouldn't happen when log_statement = all. In that case you don't need to log the portal name either. So for the normal case: LOG: parse statement: SELECT * from pg_proc LOG: execute statement: SELECT * from pg_proc and for the verbose case perhaps something like: LOG: parse statement: SELECT * from pg_proc LOG: execute statement (C_2, 42 rows): SELECT * from pg_proc LOG: fetch statement results (C_2, 7 rows) We don't have a verbose case. Why should it look different from client-side stuff? -- Bruce Momjian| http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup.| Newtown Square, Pennsylvania 19073 ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [HACKERS] statement logging / extended query protocol issues
Bruce Momjian wrote: We don't have a log_statement = verbose mode. Please see my earlier email where I suggested adding one if you really wanted all this protocol-level detail logged. -O ---(end of broadcast)--- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly
Re: [HACKERS] statement logging / extended query protocol issues
Bruce Momjian wrote: I think it is more verbose because no FETCH is logged in this type of prepare/execute. The goal, I think, is for these type of queries to look as similar to normal PREPARE/EXECUTE and DECLARE/FETCH as possible. I do not understand why this is a useful thing to do as part of log_statement. My point is that given JDBC code like this: Statement s = connection.createStatement(); ResultSet rs = s.executeQuery(SELECT * FROM pg_proc); while (rs.next()) { // Process results } it seems that the least surprising thing to get logged is simply SELECT * FROM pg_proc. I don't see how logging a synthetic PREPARE/EXECUTE/FETCH sequence (and DECLARE, now?) is useful. They're not necessarily syntactically correct, and they're certainly not queries that were actually sent to the backend. I thought log_statement was meant to answer the question what queries were submitted to the backend?, rather than to provide a trace of protocol-level activity.. -O ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster
Re: [HACKERS] statement logging / extended query protocol issues
Oliver Jowett wrote: Bruce Momjian wrote: We don't have a log_statement = verbose mode. Please see my earlier email where I suggested adding one if you really wanted all this protocol-level detail logged. We can't add that in feature freeze/beta, at least. -- Bruce Momjian| http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup.| Newtown Square, Pennsylvania 19073 ---(end of broadcast)--- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly
Re: [HACKERS] statement logging / extended query protocol issues
Oliver Jowett wrote: Bruce Momjian wrote: I think it is more verbose because no FETCH is logged in this type of prepare/execute. The goal, I think, is for these type of queries to look as similar to normal PREPARE/EXECUTE and DECLARE/FETCH as possible. I do not understand why this is a useful thing to do as part of log_statement. My point is that given JDBC code like this: Statement s = connection.createStatement(); ResultSet rs = s.executeQuery(SELECT * FROM pg_proc); while (rs.next()) { // Process results } it seems that the least surprising thing to get logged is simply SELECT * FROM pg_proc. I don't see how logging a synthetic PREPARE/EXECUTE/FETCH sequence (and DECLARE, now?) is useful. They're not necessarily syntactically correct, and they're certainly not queries that were actually sent to the backend. I thought log_statement was meant to answer the question what queries were submitted to the backend?, rather than to provide a trace of protocol-level activity.. Well, from the application writer perspective, you are right it doesn't make sense, but this is only because jdbc is using prepare internally. If you were to have written it in libpq, it would make sense, I think, and internally, this is what is happening. We can't assume only interface libraries like jdbc are using this feature. As far as I understand things, the protocol-level prepare/execute is identical to the SQL-level prepare/execute, except that there is no need to parse the execute, so it should log like the SQL-level statements, if possible. -- Bruce Momjian| http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup.| Newtown Square, Pennsylvania 19073 ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster
Re: [HACKERS] statement logging / extended query protocol issues
Bruce Momjian wrote: Well, from the application writer perspective, you are right it doesn't make sense, This is exactly what the end user is going to say. but this is only because jdbc is using prepare internally. Isn't this mostly irrelevant to the result we want to see? It's a detail of how the interface layer chooses to execute its queries, and 90% of the time the end user is not going to know or care about it. If you were to have written it in libpq, it would make sense, I think, and internally, this is what is happening. We can't assume only interface libraries like jdbc are using this feature. Wait, so is the extended query protocol the poor cousin of what libpq does, or what? You can do Parse/Bind using libpq, can't you? The *meaning* of the Parse/Bind/Execute sequence is quite clear regardless of what interface library is used. I still think that logging just the queries that were actually executed, once per execution, is the sensible thing to do here. I can't see a sequence of protocol messages that would produce a strange result if we used the rules I suggested -- do you have an example where it breaks? As far as I understand things, the protocol-level prepare/execute is identical to the SQL-level prepare/execute, except that there is no need to parse the execute, so it should log like the SQL-level statements, if possible. You can Parse any SQL statement, but you can't PREPARE any SQL statement. So, no, they're not equivalent. That's one aspect of what I meant about generating synthetic statements that weren't syntactially correct (the strange FETCH syntax with ROWS/MAXROWS that Simon was suggesting is another case). -O ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings
Re: [HACKERS] statement logging / extended query protocol issues
Simon Riggs wrote: Are we sure there is just 3 cases? I haven't exhaustively checked, but I think those are the main cases. Even if case (3) is not that common, I still want to know it is occurring, to see what effect or overhead it has. I don't want it to be more verbose than the other cases when I set log_statement = all. We'll only see the output for case (3) when someone has programmed things that way by using setFetchSize. Can we put extra output in this case into log_statement = verbose only please? (1) jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc Notice that the parse of the unnamed statement does *not* now generate a log record. What about the syntax error case? (2) jdbc parse S_1 LOG: statement: PREPARE S_1 AS SELECT * from pg_proc (perhaps this should be logged at BIND time, just like the optimization?) jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] I do not like logging queries that the driver never sent (the driver sends neither PREPARE nor EXECUTE). I also don't see why it's useful to log the statement and portal names. Can we reword this to what I suggested previously? LOG: parse statement: SELECT * from pg_proc LOG: execute statement: SELECT * from pg_proc (3) jdbc prepare S_2 LOG: statement: PREPARE S_2 AS SELECT * from pg_proc jdbc bind S_2 to C_2 jdbc execute C_2 LOG: statement: EXECUTE C_2 ROWS 42 [PREPARE: SELECT * from pg_proc] jdbc next (after cache has run out on 42nd row) v3 protocol sends E for Execute, execution halts at 49 rows for this set of bind parameters LOG: statement: FETCH C_2 ROWS 7 Again I do not like logging synthetic queries that the driver never sent (PREPARE / EXECUTE / FETCH). BTW, if you do it this way, you could get the bizarre PREPARE S_2 AS PREPARE xyz AS SELECT .. result if the application used PREPARE itself. I think that logging the second and subsequent Executes is not normally useful and shouldn't happen when log_statement = all. In that case you don't need to log the portal name either. So for the normal case: LOG: parse statement: SELECT * from pg_proc LOG: execute statement: SELECT * from pg_proc and for the verbose case perhaps something like: LOG: parse statement: SELECT * from pg_proc LOG: execute statement (C_2, 42 rows): SELECT * from pg_proc LOG: fetch statement results (C_2, 7 rows) -O ---(end of broadcast)--- TIP 6: explain analyze is your friend
Re: [HACKERS] statement logging / extended query protocol issues
On Thu, 2005-09-08 at 13:14 +1200, Oliver Jowett wrote: Simon Riggs wrote: Oliver, would it be possible to show a simplified call sequence and what you would like to see logged for each call? These are good: Maybe it should even be in the docs for the driver? It would be good if it could be written as a test within the driver, so we can expand it and test the logging. The JDBC driver generates one of these sequences: (1) Parse (unnamed statement) SELECT 1 Bind (unnamed statement - unnamed portal) Execute (unnamed portal, no row limit) (2) Parse (named statement S_1) SELECT 1 repeatedly: Bind (named statement S_1 - unnamed portal) Execute (unnamed portal, no row limit) (3) Parse (named statement S_2) SELECT 1 repeatedly: Bind (named statement S_2 - named portal C_2) repeatedly: Execute (named portal C_2, row limit 42) Are we sure there is just 3 cases? Ideal output is: (1) LOG: statement: SELECT 1 (2) LOG: statement: SELECT 1 LOG: statement: SELECT 1 LOG: statement: SELECT 1 (3) LOG: statement: SELECT 1 LOG: statement: SELECT 1 LOG: statement: SELECT 1 In case (3), that's one log line per repeat of the outer loop, regardless of how many Executes are sent in the inner loop. Note that case (1) is the most common case for application queries via the JDBC driver, and case (2) is the most common for internally generated statements like BEGIN. Even if case (3) is not that common, I still want to know it is occurring, to see what effect or overhead it has. As you can see from the output I'd like, I don't think that synthesizing FETCH / EXECUTE queries that don't actually exist [is a] useful thing to do, at least at the Joe Average User level. Your original point at the top of this thread was valid: a get-next-rows shouldn't look like a re-execute. We can call it something else if you like, as long as we can tell the difference. We'll only see the output for case (3) when someone has programmed things that way by using setFetchSize. Also note that the JDBC driver doesn't exercise all of the extended protocol -- for example it's possible to re-Bind the same unnamed statement repeatedly, or have multiple Executes on an unnamed portal with a row limit, but the JDBC driver never does that. I agree there's not much gained from displaying the BIND statement as it is. I argued previously against including the BIND parameters. Now I would say we should either include them or leave out BIND altogether. Here's a new suggestion and patch that brings together - Oliver and Simon's wish to remove BIND from normal logging - Oliver's suggestion to remove the PREPARE logging for unnamed statements, which would otherwise double-up logging for case(1) - Bruce and Simon's view to keep some form of FETCH logging - Tom's view to rationalise the way ROWS is mentioned (lines beginning jdbc don't show in the log, but are just there to show clearly the time sequence of activities and what gets subsequently logged) (1) Parse (unnamed statement) SELECT * from pg_proc Bind (unnamed statement - unnamed portal) Execute (unnamed portal, no row limit) (1) jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc jdbc parse jdbc bind jdbc execute LOG: statement: SELECT * from pg_proc Notice that the parse of the unnamed statement does *not* now generate a log record. (2) Parse (named statement S_1) SELECT * from pg_proc repeatedly: Bind (named statement S_1 - unnamed portal) Execute (unnamed portal, no row limit) (2) jdbc parse S_1 LOG: statement: PREPARE S_1 AS SELECT * from pg_proc (perhaps this should be logged at BIND time, just like the optimization?) jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] jdbc bind S_1 jdbc execute LOG: statement: EXECUTE unnamed [PREPARE: SELECT * from pg_proc] ...I wonder if unnamed just confuses what is going on here? I've left it in for now, but suggest that we take that out again? (3) Parse (named statement S_2) SELECT * from pg_proc repeatedly: Bind (named statement S_2 - named portal C_2) repeatedly: Execute (named portal C_2, row limit 42) (3) jdbc prepare S_2 LOG: statement: PREPARE S_2 AS SELECT * from pg_proc jdbc bind S_2 to C_2 jdbc execute C_2 LOG: statement: EXECUTE C_2 ROWS 42 [PREPARE: SELECT * from pg_proc] jdbc next (after cache has run out on 42nd row) v3 protocol sends E for Execute, execution halts at 49 rows for this set of bind parameters LOG: statement: FETCH C_2 ROWS 7 jdbc bind S_2 to C_2 jdbc execute C_2 LOG: statement: EXECUTE C_2 ROWS 42 [PREPARE: SELECT * from pg_proc] jdbc next (after cache has run out on 42nd row) v3 protocol sends E for Execute LOG:
Re: [HACKERS] statement logging / extended query protocol issues
Oh, I didn't realize a FETCH would show up as an EXECUTE. That is wrong and should be fixed because a user-level FETCH shows up as a fetch, not as the original query. --- Simon Riggs wrote: Oliver Jowett wrote: 8.1-beta1 produces some odd results with statement logging enabled when the extended query protocol is used (e.g. when using the JDBC driver). Repeatedly running a simple query with log_statement = 'all' produces this: ... Secondly, running a query that uses portals produces output like this: LOG: statement: PREPARE S_3 AS SELECT * from pg_proc LOG: statement: BIND C_4 LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] Comments: - The BIND is still fairly content-free. - The EXECUTEs are a bit misleading as the SELECT was actually only run once (there are multiple Execute messages for the same portal). You could infer that there is only one SELECT from the repeated portal name and the lack of an intervening BIND, I suppose. I've put together this prototype to offer more useful messages in the situation Oliver describes. Subsequent calls to the same portal are described as FETCHes rather than as EXECUTEs. The portal name is still given and number of rows is provided also. I haven't tested this with the java program supplied, since this is a fairly short-hack for comments. I'll correct any mistakes before submission to patches. Comments? Best Regards, Simon Riggs [ Attachment, skipping... ] -- Bruce Momjian| http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup.| Newtown Square, Pennsylvania 19073 ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster
Re: [HACKERS] statement logging / extended query protocol issues
On Thu, 2005-09-08 at 13:14 +1200, Oliver Jowett wrote: Simon Riggs wrote: On Tue, 2005-09-06 at 07:47 +, Oliver Jowett wrote: Simon Riggs wrote: Looking more closely, I don't think either is correct. Both can be reset according to rewind operations - see DoPortalRewind(). We'd need to add another bool onto the Portal status data structure. AFAIK this is only an issue with SCROLLABLE cursors, which v3 portals aren't. OK, that may be so, but the internals don't know that. If I use atEnd or atStart then messages would differ from v3 to v2. It would then be easy to confuse v2 cursor actions with multiple re-executions in v3. I want to be able to look at the log and work out what happened, not to start asking questions like do you use v2, v3 or a mix of both?. Uh, but the logging in question only runs from exec_execute_message, which is explicitly handling a v3 Execute message, not an EXECUTE or FETCH from somewhere else? If that can be confused with a v2 query, then we should be logging it in such a way that it doesn't get confused (this is one reason why I don't like your approach of synthesizing FETCH/EXECUTE statements that were never actually submitted by the client). I don't think we should worry about trying to support v3 Execute against a SCROLLABLE cursor created via DECLARE that has been rewound -- that's a strange case and there was some discussion previously about separating the v3 portal vs. cursor namespaces anyway. OK, if everybody is saying dont worry, I'll switch it to use atStart. Best Regards, Simon Riggs ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [HACKERS] statement logging / extended query protocol issues
On Tue, 2005-09-06 at 07:47 +, Oliver Jowett wrote: Simon Riggs wrote: Looking more closely, I don't think either is correct. Both can be reset according to rewind operations - see DoPortalRewind(). We'd need to add another bool onto the Portal status data structure. AFAIK this is only an issue with SCROLLABLE cursors, which v3 portals aren't. OK, that may be so, but the internals don't know that. If I use atEnd or atStart then messages would differ from v3 to v2. It would then be easy to confuse v2 cursor actions with multiple re-executions in v3. I want to be able to look at the log and work out what happened, not to start asking questions like do you use v2, v3 or a mix of both?. If queries are short and yet there is much fetching, we may see a program whose main delay is because of program-to-server delay because of fetching. So, I'd like to see that in the log, but I agree with your earlier comments that it should be a shorter log line. I'm coming from the point of view of a user who wants to just turn on query logging. The mechanics of the portals aren't of interest to them. Currently, log_statement = all produces markedly different output depending on whether the extended query protocol is used or not, which is very much an implementation detail.. ...and I hope it would, since the impact on the server differs. I want the log to reflect what has happened on the server. How about log_statement = verbose or something similar to enable logging of all the details, and have all just log Parse and the first Execute? I think I like that suggestion. IMHO the client/server interaction is often worth reviewing as part of a performance analysis, so I do want to include all of that detail, but it sounds like a good idea to be able to turn off the noise once that aspect has been examined. How would that suggestion work when we use log_min_duration_statement? Oliver, would it be possible to show a simplified call sequence and what you would like to see logged for each call? That would simplify the process of gaining agreement and would give a simple spec for me to code. We're into beta now, so I don't want to stretch people's patience too much further by changes in this area. I ask you since I think you have a better grasp on the various protocols than I do. I'll work on a further recoding of what we have been discussing. Best Regards, Simon Riggs ---(end of broadcast)--- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq
Re: [HACKERS] statement logging / extended query protocol issues
On Mon, 2005-09-05 at 15:38 -0400, Tom Lane wrote: Simon Riggs [EMAIL PROTECTED] writes: + /* + * If we re-issue an Execute protocol request against an existing + * portal, then we are only fetching more rows rather than + * completely re-executing the query from the start + */ + if (!portal-atEnd) + subsequent_fetch = true; That strikes me as a completely bogus test for a re-issued execute. Did you mean !atStart? Looking more closely, I don't think either is correct. Both can be reset according to rewind operations - see DoPortalRewind(). We'd need to add another bool onto the Portal status data structure. Also, why is it a good idea to report the number of rows fetched in some cases (and not others)? The number of rows fetched seemed particularly important on a FETCH operation. Although they are logically part of the same query, some queries have a lengthy pre-execution preparation time (e.g. sort) and others don't. (To Oliver:) If queries are short and yet there is much fetching, we may see a program whose main delay is because of program-to-server delay because of fetching. So, I'd like to see that in the log, but I agree with your earlier comments that it should be a shorter log line. If we see FETCH unnamed ROWS 1 FETCH unnamed ROWS 1 FETCH unnamed ROWS 1 we'd know the fetchsize was inappropriately set and correct it. I guess we could add in a number of rows on the other log lines also if people want that. I like the idea... it would tell us which queries are causing huge retrievals. Best Regards, Simon Riggs ---(end of broadcast)--- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq
Re: [HACKERS] statement logging / extended query protocol issues
Simon Riggs wrote: Looking more closely, I don't think either is correct. Both can be reset according to rewind operations - see DoPortalRewind(). We'd need to add another bool onto the Portal status data structure. AFAIK this is only an issue with SCROLLABLE cursors, which v3 portals aren't. If queries are short and yet there is much fetching, we may see a program whose main delay is because of program-to-server delay because of fetching. So, I'd like to see that in the log, but I agree with your earlier comments that it should be a shorter log line. I'm coming from the point of view of a user who wants to just turn on query logging. The mechanics of the portals aren't of interest to them. Currently, log_statement = all produces markedly different output depending on whether the extended query protocol is used or not, which is very much an implementation detail.. How about log_statement = verbose or something similar to enable logging of all the details, and have all just log Parse and the first Execute? Ideally, even Parse wouldn't be logged, but then we'd need a way to log statements that error during Parse. -O ---(end of broadcast)--- TIP 6: explain analyze is your friend
Re: [HACKERS] statement logging / extended query protocol issues
Oliver Jowett wrote: 8.1-beta1 produces some odd results with statement logging enabled when the extended query protocol is used (e.g. when using the JDBC driver). Repeatedly running a simple query with log_statement = 'all' produces this: ... Secondly, running a query that uses portals produces output like this: LOG: statement: PREPARE S_3 AS SELECT * from pg_proc LOG: statement: BIND C_4 LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] Comments: - The BIND is still fairly content-free. - The EXECUTEs are a bit misleading as the SELECT was actually only run once (there are multiple Execute messages for the same portal). You could infer that there is only one SELECT from the repeated portal name and the lack of an intervening BIND, I suppose. I've put together this prototype to offer more useful messages in the situation Oliver describes. Subsequent calls to the same portal are described as FETCHes rather than as EXECUTEs. The portal name is still given and number of rows is provided also. I haven't tested this with the java program supplied, since this is a fairly short-hack for comments. I'll correct any mistakes before submission to patches. Comments? Best Regards, Simon Riggs Index: src/backend/tcop/postgres.c === RCS file: /projects/cvsroot/pgsql/src/backend/tcop/postgres.c,v retrieving revision 1.457 diff -c -c -r1.457 postgres.c *** src/backend/tcop/postgres.c 11 Aug 2005 21:11:45 - 1.457 --- src/backend/tcop/postgres.c 5 Sep 2005 18:57:22 - *** *** 1681,1686 --- 1681,1687 bool save_log_duration = log_duration; int save_log_min_duration_statement = log_min_duration_statement; bool save_log_statement_stats = log_statement_stats; + boolsubsequent_fetch = false; /* Adjust destination to tell printtup.c what to do */ dest = whereToSendOutput; *** *** 1693,1698 --- 1694,1707 (errcode(ERRCODE_UNDEFINED_CURSOR), errmsg(portal \%s\ does not exist, portal_name))); + /* + * If we re-issue an Execute protocol request against an existing + * portal, then we are only fetching more rows rather than + * completely re-executing the query from the start + */ + if (!portal-atEnd) + subsequent_fetch = true; + /* * If the original query was a null string, just return * EmptyQueryResponse. *** *** 1704,1710 return; } ! if (portal-sourceText) { debug_query_string = portal-sourceText; pgstat_report_activity(portal-sourceText); --- 1713,1724 return; } ! if (subsequent_fetch) ! { ! debug_query_string = fetch message; ! pgstat_report_activity(FETCH); ! } ! else if (portal-sourceText) { debug_query_string = portal-sourceText; pgstat_report_activity(portal-sourceText); *** *** 1730,1739 ResetUsage(); if (log_statement == LOGSTMT_ALL) ! /* We have the portal, so output the source query. */ ! ereport(LOG, (errmsg(statement: EXECUTE %s [PREPARE: %s], portal_name, portal-sourceText ? portal-sourceText : ))); BeginCommand(portal-commandTag, dest); --- 1744,1760 ResetUsage(); if (log_statement == LOGSTMT_ALL) ! { ! if (subsequent_fetch) ! ereport(LOG, ! (errmsg(statement: FETCH %s ROWS %ld, portal_name, ! max_rows))); ! else ! /* We have the portal, so output the source query. */ ! ereport(LOG, (errmsg(statement: EXECUTE %s [PREPARE: %s], portal_name, portal-sourceText ? portal-sourceText : ))); + } BeginCommand(portal-commandTag, dest); *** *** 1862,1874 if (save_log_min_duration_statement == 0 || (save_log_min_duration_statement 0 usecs = save_log_min_duration_statement * 1000)) ! ereport(LOG, (errmsg(duration: %ld.%03ld ms statement: EXECUTE %s [PREPARE: %s], (long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 + (stop_t.tv_usec - start_t.tv_usec) / 1000), (long) (stop_t.tv_usec - start_t.tv_usec) % 1000, portal_name, portal-sourceText ? portal-sourceText : ))); } if (save_log_statement_stats) --- 1883,1906 if (save_log_min_duration_statement == 0 || (save_log_min_duration_statement 0 usecs = save_log_min_duration_statement * 1000)) ! { ! if (subsequent_fetch) ! ereport(LOG, !
Re: [HACKERS] statement logging / extended query protocol issues
Simon Riggs [EMAIL PROTECTED] writes: + /* + * If we re-issue an Execute protocol request against an existing + * portal, then we are only fetching more rows rather than + * completely re-executing the query from the start + */ + if (!portal-atEnd) + subsequent_fetch = true; That strikes me as a completely bogus test for a re-issued execute. Did you mean !atStart? Also, why is it a good idea to report the number of rows fetched in some cases (and not others)? regards, tom lane ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [HACKERS] statement logging / extended query protocol issues
Simon Riggs wrote: Subsequent calls to the same portal are described as FETCHes rather than as EXECUTEs. The portal name is still given and number of rows is provided also. I wonder if it might be better to only log the first Execute.. It's not immediately clear to me that it's useful to see all the individual fetches when they're logically part of a single query. -O ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings
Re: [HACKERS] statement logging / extended query protocol issues
I have applied the following patch to output unnamed for unnamed prepared statements. As far as your other issues, how would you want server-side statements to be logged? statement: is a log label for a statement. What else should we use? --- Oliver Jowett wrote: 8.1-beta1 produces some odd results with statement logging enabled when the extended query protocol is used (e.g. when using the JDBC driver). Repeatedly running a simple query with log_statement = 'all' produces this: LOG: statement: PREPARE AS SELECT 'dummy statement' LOG: statement: BIND LOG: statement: EXECUTE [PREPARE: SELECT 'dummy statement'] [...] LOG: statement: PREPARE S_2 AS SELECT 'dummy statement' LOG: statement: BIND LOG: statement: EXECUTE [PREPARE: SELECT 'dummy statement'] LOG: statement: BIND LOG: statement: EXECUTE [PREPARE: SELECT 'dummy statement'] LOG: statement: BIND [...] Comments: - The PREPARE lines are misleading as the query actually sent does not include PREPARE at all. - The driver never sends EXECUTE as a statement, but it is logged as one. - PREPARE AS is a confusing way of saying the unnamed statement - The BIND lines are content-free. Secondly, running a query that uses portals produces output like this: LOG: statement: PREPARE S_3 AS SELECT * from pg_proc LOG: statement: BIND C_4 LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] Comments: - The BIND is still fairly content-free. - The EXECUTEs are a bit misleading as the SELECT was actually only run once (there are multiple Execute messages for the same portal). You could infer that there is only one SELECT from the repeated portal name and the lack of an intervening BIND, I suppose. 8.1 is admittedly better than 8.0 here (8.0 had no logging in this case at all).. but it's not very user-friendly as it stands. I'm sure the JDBC list is going to get lots of why does statement logging give me this weird output questions :/ I've attached the Java code I used to produce this. It expects a single argument, the JDBC URL to use, e.g. 'jdbc:postgresql://localhost:8101/test?user=oliver' -O import java.sql.*; import java.util.*; public class TestStatementLogging { public static void main(String[] args) throws Exception { Class.forName(org.postgresql.Driver); Connection conn = DriverManager.getConnection(args[0]); conn.setAutoCommit(false); PreparedStatement stmt = conn.prepareStatement(SELECT 'dummy statement'); for (int j = 0; j 10; ++j) stmt.executeQuery(); stmt.close(); stmt = conn.prepareStatement(SELECT * from pg_proc); stmt.setFetchSize(1); ResultSet rs = stmt.executeQuery(); while (rs.next()) ; stmt.close(); conn.createStatement().execute(I am a syntax error); } } ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster -- Bruce Momjian| http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup.| Newtown Square, Pennsylvania 19073 Index: src/backend/tcop/postgres.c === RCS file: /cvsroot/pgsql/src/backend/tcop/postgres.c,v retrieving revision 1.457 diff -c -c -r1.457 postgres.c *** src/backend/tcop/postgres.c 11 Aug 2005 21:11:45 - 1.457 --- src/backend/tcop/postgres.c 2 Sep 2005 21:46:20 - *** *** 1164,1170 if (log_statement == LOGSTMT_ALL) ereport(LOG, ! (errmsg(statement: PREPARE %s AS %s, stmt_name, query_string))); /* * Start up a transaction command so we can run parse analysis etc. --- 1164,1172 if (log_statement == LOGSTMT_ALL) ereport(LOG, ! (errmsg(statement: PREPARE %s AS %s, ! (*stmt_name != '\0') ? stmt_name : unnamed, ! query_string))); /* * Start up a transaction command so we can run parse analysis etc. *** *** 1732,1738 if (log_statement == LOGSTMT_ALL) /* We have the portal, so output the source query. */ ereport(LOG, !
[HACKERS] statement logging / extended query protocol issues
8.1-beta1 produces some odd results with statement logging enabled when the extended query protocol is used (e.g. when using the JDBC driver). Repeatedly running a simple query with log_statement = 'all' produces this: LOG: statement: PREPARE AS SELECT 'dummy statement' LOG: statement: BIND LOG: statement: EXECUTE [PREPARE: SELECT 'dummy statement'] [...] LOG: statement: PREPARE S_2 AS SELECT 'dummy statement' LOG: statement: BIND LOG: statement: EXECUTE [PREPARE: SELECT 'dummy statement'] LOG: statement: BIND LOG: statement: EXECUTE [PREPARE: SELECT 'dummy statement'] LOG: statement: BIND [...] Comments: - The PREPARE lines are misleading as the query actually sent does not include PREPARE at all. - The driver never sends EXECUTE as a statement, but it is logged as one. - PREPARE AS is a confusing way of saying the unnamed statement - The BIND lines are content-free. Secondly, running a query that uses portals produces output like this: LOG: statement: PREPARE S_3 AS SELECT * from pg_proc LOG: statement: BIND C_4 LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] LOG: statement: EXECUTE C_4 [PREPARE: SELECT * from pg_proc] Comments: - The BIND is still fairly content-free. - The EXECUTEs are a bit misleading as the SELECT was actually only run once (there are multiple Execute messages for the same portal). You could infer that there is only one SELECT from the repeated portal name and the lack of an intervening BIND, I suppose. 8.1 is admittedly better than 8.0 here (8.0 had no logging in this case at all).. but it's not very user-friendly as it stands. I'm sure the JDBC list is going to get lots of why does statement logging give me this weird output questions :/ I've attached the Java code I used to produce this. It expects a single argument, the JDBC URL to use, e.g. 'jdbc:postgresql://localhost:8101/test?user=oliver' -O import java.sql.*; import java.util.*; public class TestStatementLogging { public static void main(String[] args) throws Exception { Class.forName(org.postgresql.Driver); Connection conn = DriverManager.getConnection(args[0]); conn.setAutoCommit(false); PreparedStatement stmt = conn.prepareStatement(SELECT 'dummy statement'); for (int j = 0; j 10; ++j) stmt.executeQuery(); stmt.close(); stmt = conn.prepareStatement(SELECT * from pg_proc); stmt.setFetchSize(1); ResultSet rs = stmt.executeQuery(); while (rs.next()) ; stmt.close(); conn.createStatement().execute(I am a syntax error); } } ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster