Wunderliche Queries aus psql-odbc treiber & M$Access

Hi zusammen,
ich scanne grade serverlogfiles (developmentserver pg7.4, debian linux) und finde bergeweise queries wiefolgt (man beachte die WHERE clause):

[23-2] LOCATION:  pg_parse_query, postgres.c:464
[24-1] LOG:  00000: statement: BEGIN;declare "SQL_CUR09B39300" cursor with hold for SELECT 

[24-2] "pkey","created","fdeleted","deletedby","variable_owner","variable_name","bsystemwi
[24-3] de","variable_value","variable_comment"  FROM "public"."_tbl_system_variables"  WHERE "pkey" = '18' OR "pkey" = '20' OR "pkey" =
[24-4]  '21' OR "pkey" = '22' OR "pkey" = '22' OR "pkey" = '22' OR "pkey" = '22' OR "pkey" = '22' OR "pkey" = '22' OR "pkey" =
[24-5]  '22';fetch 100 in "SQL_CUR09B39300"

Korrekt wären diese Queries OHNE Where clause, da die gelisteten keys alle vorhandenen Datensätze beinhalten…

Es wird also statt einem einfachen ‘Select x from table’ ein ‘select x from table where (pkey= schleife über alle pkeys)’ abgesetzt.

Nach etwas Recherche fand ich die Urheber-Applikation: M$ Access, wie nicht anders zu erwarten :wink:


Hintergrund
Wir migrieren grade eine kleine M$ Datenbank in 2 Schritten auf
a.) Postgres
2.) c## Frontend

Die Queries mit WHERE(pkey= pkey= pkey=) werden also offensichtlich generiert, wenn ein select auf eine ODBC-verknüfte Tabelle durchgeführt wird.

Frag1: Hat irgend einer von euch sowas schon mal gesehen?
Frage 2: Woher glaubt denn M$ oder der odbc-treiber die Informationen zu nehmen, welche keys die datenbank grade enthält? Es erfolgt davor keine query, um die Pkeys aller datensätze abzufragen …


Danke im Vorraus

Jochen

7.4? Das stinkt schon nach Verwesung.

Korrekt wären diese Queries OHNE Where clause, da die gelisteten keys alle vorhandenen Datensätze beinhalten…

Hat die Tabelle einen Primary Key? IIRC macht Access und/oder ODBC gar wunderliche Dinge, wenn da kein PK ist.

Es wird also statt einem einfachen ‘Select x from table’ ein ‘select x from table where (pkey= schleife über alle pkeys)’ abgesetzt.

Also, das ist als PK definiert? Das ist, ähm, ja.

Nach etwas Recherche fand ich die Urheber-Applikation: M$ Access, wie nicht anders zu erwarten > :wink:


Hintergrund
Wir migrieren grade eine kleine M$ Datenbank in 2 Schritten auf
a.) Postgres
2.) c## Frontend

Die Queries mit WHERE(pkey= pkey= pkey=) werden also offensichtlich generiert, wenn ein select auf eine ODBC-verknüfte Tabelle durchgeführt wird.

Frag1: Hat irgend einer von euch sowas schon mal gesehen?
Frage 2: Woher glaubt denn M$ oder der odbc-treiber die Informationen zu nehmen, welche keys die datenbank grade enthält? Es erfolgt davor keine query, um die Pkeys aller datensätze abzufragen …

IIRC wird beim Aufbau der ODBC-Verbindung durch den ODBC-Treiber das Schema der kompletten DB ausgelesen, dann aber nicht mehr.

Andreas

Hi Andreas,

7.4? Das stinkt schon nach Verwesung.

yo, die haben ne 7.4er im haus und wollen nicht upgraden …

Also, das ist als PK definiert?

yupp

Das ist, ähm, ja.

ähm ja was :wink:

dankdir

jochen

ok,
eine Teilerklärung habe ich schon.

[23-2] LOCATION: pg_parse_query, postgres.c:464
[24-1] LOG: 00000: statement: BEGIN;declare “SQL_CUR09B39300” cursor with hold for SELECT

[24-2] “pkey”,“created”,“fdeleted”,“deletedby”,“variable_owner”,“variable_name”,“bsystemwi
[24-3] de”,“variable_value”,“variable_comment” FROM “public”.“_tbl_system_variables” WHERE “pkey” = ‘18’ OR “pkey” = ‘20’ OR “pkey” =
[24-4] ‘21’ OR “pkey” = ‘22’ OR “pkey” = ‘22’ OR “pkey” = ‘22’ OR “pkey” = ‘22’ OR “pkey” = ‘22’ OR “pkey” = ‘22’ OR “pkey” =
[24-5] ‘22’;fetch 100 in “SQL_CUR09B39300”

Scheint als würde Access dafür verwantwortlich sein und bei jeder Query auf verlinkte tables 10er-Weise die Daten beschaffen, daher der grausige Spagetticode.

Werden Queries mit mehr als 10 Datensätzen im Result abgesetzt, erfolgen serverseitig tatsächlich mehrere Queries nacheinander(!), um alle Datensätze, die grade benötigt werden, abzufragen.

Scheint ne seltsame Form der Traffic-Optimierung darzustellen :frowning:

Stellt sich nur noch die Frage, ob es sich lohnt, zu versuchen, access das abzugewöhnen…

Wieso wunderliche Queries?


Nein. Das Query hat ein Programmierer definiert und damit auch die Bedingungen in der WHERE-KLAUSEL.


Nein, es wird das abgesetzt, was der Programmierer in seinem Code definiert hat. Zudem ist im obigen Code eine Limit für 100 Datensätze vorgegeben.


Prima. Was kann ein Werkzeug dafür, wenn Dir das nötige Wissen fehlt?


Nein, die Queries sind vorher schon im Code der Applikation vorhanden.


Ja. Was soll das ungewöhnliche an dem Code sein? Das ist ein ganz normaler SELEKT mit einigen Zusatzinformation über den internen Namen des Cursors, der aber erst zur Ausführungszeit durch das Programm erzeugt wird.


M$ oder der ODBC-Treiber glauben an garnichts. Sie führen nur den Code aus, den vorher ein Programmierer in der Applikation programmiert hat.





mfg

fristo

Hi Fristo,
danke für Deine -wenn auch etwas unfreundliche?- Antwort, schlechten Tag gehabt? :slight_smile:

Prima. Was kann ein Werkzeug dafür, wenn Dir das nötige Wissen fehlt?

Allerdings schienst Du auch ein versierter und kompromissloser Verfechter von Access zu sein, und damit ein potentiell wertvoller Ansprechpartner in dieser Sache :wink:

Insofern würde ich dich gerne um eine überdachte Antwort bitten, allerdings unter Annahme folgender Fakten, die Du getrost als gegeben anehmen darfst:

1.) Nimm an, ich würde mich gut genug mit Access auskennen, um vollkommen ausschließen zu können, dass diese Query in irgend einer Form von einem besoffenen Programmierer geschrieben wurde, das gepastete Select-Statement wird tatsächlich von Access in Kombination mit dem Treiber erzeugt . Es ist kein vba-Code involviert.

2.) Nimm ebenfalls an, dass dieser Effekt defacto (auf meinem Server (in diesem Fall PG7.4) Nachtrag: gleiches gilt für serverversion 8.1) mit meinem ODBC-Treiber (PostgreSQL Unicode v. 8.02.05.00 ) und meiner Access-Version (in diesem Fall 2003)) auftritt, wenn ich ganz simpel eine Tabelle mittels odbc verlinke und dann mit Doppelklick öffne.

Es ist dabei vollkommen unerheblich, welche Tabelle ich verlinke, der Effekt tritt bei allen Tabellen auf!


3.) Nimm ebenfalls an, dass es gar nicht so unwahrscheinlich ist, dass dies sogar ein gewollter Effekt ist - wie ja bereits in meiner letzten Nachricht geschrieben - da ein einem ‘Datenbaltt’ immer nur ein Teil der Datensätze angezeigt werden muss, warum also die gesamte Tabelle auf einmal auslesen.

4.) Nimm an, dass ich der Meinung bin, dass ich - falls ich in der Lage wäre, diesen Effekt zu beinflussen - dieses gerne täte, da mir nicht gefällt, was in diesen Fällen bei komplexeren Queries an den Datenbankserver geschickt wird, und ich denke, dass wir da was performanteres hinbekommen.

5.) Nimm ebenfalls an, dass mir natärlich klar ist, dass ich das ganze Problem mittels sql-Passthough und views umgehen kann, ich fand nur den Effekt verwunderlich und bemerkenswert.

Isofern meine Fragen nochmal:
Frage 1: Hast du diesen Effekt schon mal gesehen?
Frage 2: Wenn vor der Ausführung der Query auf dem Server die Menge der zum Zeitpunkt verfügbaren Datensätze (und deren pkeys) nicht abgefragt wird (zumindet sehe ich nichts entsprechendes im Log), könnte es dann nicht sein, dass in einem Mehrbenutzerumfeld Datensätze nicht angezeigt werden, obwohl bereits committed?

Danke

jochen

Hallo Jochen

Nein, ich habe keinen schlechten Tag gehabt. Die nach Deiner Meinung etwas unfreundliche Antwort bezieht sich auf Deine Bemerkung “M$ Access, wie nicht anders zu erwarten”. Ich kenne genügend andere Programme, die ebenso guten/schlechten (?) Code liefern, wie M$ Access. Warum Bashing statt Sachlichkeit?


Absolut nicht. Access liegt in der hintersten Schublade. Ich werde Access selbst für private Anwendungen nicht einsetzen. Der Aufwand, eine sauber Applikation damit zu erstellen, ist mir zu aufwendig. Allerdings habe ich einige Applikation damit erstellt.


Na ja, um Dir zu helfen habe ich nun Access doch installiert und eine ODBC-Verbindung zu einer PostgreSQL-Datenbank erstellt. Was dann auch zu überraschenden Ergebnissen führte:

Zum jetzigen Zeitpunkt kann ich sagen, dass die 4 Datensätze in Deiner Datenbank nicht ausreichen um eine eindeutige Aussage zu erstellen. Zudem sind die Information in Deiner LOG-Datei unvollständig. Entgegen Deinen Annahmen holt sich Access vorab sämtliche Pkey’s. Hier die wichtigsten Auszüge aus meiner LOG-Datei:

2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: StartTransactionCommand
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  start_xact_command, postgres.c:2200
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "public"."foo"."i" FROM "public"."foo" ORDER BY "public"."foo"."i"  
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: StartTransaction
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionState, xact.c:3991
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "public"."foo"."i" FROM "public"."foo" ORDER BY "public"."foo"."i"  
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: name: unnamed; blockState:       DEFAULT; state: INPROGR, xid/subid/cid: 48315/1/0, nestlvl: 1, children: <>
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionStateRec, xact.c:4016
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "public"."foo"."i" FROM "public"."foo" ORDER BY "public"."foo"."i"  
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: CommitTransactionCommand
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  finish_xact_command, postgres.c:2224
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "public"."foo"."i" FROM "public"."foo" ORDER BY "public"."foo"."i"  
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: CommitTransaction
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionState, xact.c:3991
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "public"."foo"."i" FROM "public"."foo" ORDER BY "public"."foo"."i"  
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 48315/1/0, nestlvl: 1, children: <>
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionStateRec, xact.c:4016
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "public"."foo"."i" FROM "public"."foo" ORDER BY "public"."foo"."i"  
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: StartTransactionCommand
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  start_xact_command, postgres.c:2200
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 0 OR "i" = 1 OR "i" = 2 OR "i" = 3 OR "i" = 4 OR "i" = 5 OR "i" = 6 OR "i" = 7 OR "i" = 8 OR "i" = 9
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: StartTransaction
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionState, xact.c:3991
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 0 OR "i" = 1 OR "i" = 2 OR "i" = 3 OR "i" = 4 OR "i" = 5 OR "i" = 6 OR "i" = 7 OR "i" = 8 OR "i" = 9
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: name: unnamed; blockState:       DEFAULT; state: INPROGR, xid/subid/cid: 48316/1/0, nestlvl: 1, children: <>
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionStateRec, xact.c:4016
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 0 OR "i" = 1 OR "i" = 2 OR "i" = 3 OR "i" = 4 OR "i" = 5 OR "i" = 6 OR "i" = 7 OR "i" = 8 OR "i" = 9
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: CommitTransactionCommand
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  finish_xact_command, postgres.c:2224
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 0 OR "i" = 1 OR "i" = 2 OR "i" = 3 OR "i" = 4 OR "i" = 5 OR "i" = 6 OR "i" = 7 OR "i" = 8 OR "i" = 9
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: CommitTransaction
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionState, xact.c:3991
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 0 OR "i" = 1 OR "i" = 2 OR "i" = 3 OR "i" = 4 OR "i" = 5 OR "i" = 6 OR "i" = 7 OR "i" = 8 OR "i" = 9
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 48316/1/0, nestlvl: 1, children: <>
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionStateRec, xact.c:4016
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 0 OR "i" = 1 OR "i" = 2 OR "i" = 3 OR "i" = 4 OR "i" = 5 OR "i" = 6 OR "i" = 7 OR "i" = 8 OR "i" = 9
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: StartTransactionCommand
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  start_xact_command, postgres.c:2200
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 10 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: StartTransaction
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionState, xact.c:3991
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 10 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: name: unnamed; blockState:       DEFAULT; state: INPROGR, xid/subid/cid: 48317/1/0, nestlvl: 1, children: <>
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionStateRec, xact.c:4016
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 10 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: CommitTransactionCommand
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  finish_xact_command, postgres.c:2224
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 10 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: CommitTransaction
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionState, xact.c:3991
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 10 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11
2007-12-07 04:04:19 fristo 127.0.0.1(1041) DEBUG:  00000: name: unnamed; blockState:       STARTED; state: INPROGR, xid/subid/cid: 48317/1/0, nestlvl: 1, children: <>
2007-12-07 04:04:19 fristo 127.0.0.1(1041) LOCATION:  ShowTransactionStateRec, xact.c:4016
2007-12-07 04:04:19 fristo 127.0.0.1(1041) STATEMENT:  SELECT "i","j"  FROM "public"."foo"  WHERE "i" = 10 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11 OR "i" = 11

Die Tabelle besteht aus aus den Spalten i und j wobei i der PKey ist. In der Tabelle sind 12 Datensätze enthalten.

Auch dass Access immer nur 10 Datensätze von der Datenbank abholt, geht aus der LOG-Datei hervor. Ich glaube allerdings nicht, dass Du dieses Access abgewöhnen kannst.

Deine Fragen sollten damit geklärt sein.





mfg

fristo

Hi Fristo,
erstmal vielen Dank für die viele Mühe, die Du dir gemacht hast, ich bin also glücklicher Weise nicht Allein :wink:

Ja, das denke ich inzwischen auch.

Entgegen Deinen Annahmen holt sich Access vorab sämtliche Pkey’s.

Hmm, seltsam,ich hab kein entsprechendes Statement in meinen Logs gefunden,(das hat mich ja derart verwirrt), muss ich nochmal checken, vielleicht fahr ich falsche Log-Einstellungen …



Nur de Vollständigkeit halber:
Verwendest Du auch den ‘offiziellen’ psql-odbc-treiber oder ne Alternative?

Danke vom Vorraus


Jochen

Hallo Jochen

Ich habe in postgresql.conf folgende Einstellungen geändert (Version 8.2.5-1):

client_min_messages = debug5
log_min_messages = debug5
log_error_verbosity = verbose
log_min_error_statement = debug5



JDBC, also Java. Ich würde aber die offiziellen psql-odbc-treiber verwenden. PostgreSQL wird ja auch immer weiter entwickelt und andere Treiber hinken dann hinter dem aktuellen Stand her. Bezüglich ODBC-Treiber hat es hier auch nur wenige Beträge gegeben. Welche ODBC-Treiber in der Praxis verwendet werden, ist daher hier unbekannt. Na ja, wenn die Applikation richtig funktioniert, sollte das auch keine Rolle spielen.




mfg

fristo

Hallo Fristo,
danke für deine Antwort.
Settings übernommen … aaaaah,peinlich, peinlich :wink: ->jetzt seh ich die Query auch

danke and have a nice weekend


jochen