2015-01-28 22 views
6

Ich habe einen funktionalen Index für eine Sybase-Tabelle erstellt.Warum sollte Sybase keinen funktionalen Index verwenden?

create index acadress_codpost_lower on acadress(LOWER(l5_codpost)) 

Ich führe dann eine komplexe Abfrage, die den Index verwendet. Ohne den Index dauert es 17,086 Sekunden. Mit dem Index dauert es 0,076 Sekunden.

Ich habe es von zwei verschiedenen SQL-Clients und auf Sybase-Servern für Entwicklung und Pre-Prod ausgeführt. In allen Fällen sehe ich die Beschleunigung aus dem Index.

Wenn wir jedoch eine identische Abfrage von Java ausführen (und ich weiß, dass es identisch ist, da ich das generierte SQL protokolliert und direkt in den SQL-Clients verwendet habe), ist die Leistung genau so wie vor dem Hinzufügen der Indizes.

Welchen möglichen Grund könnte es geben, dass identische SQL-Abfragen den Index verwenden, wenn sie von ACE und SQuirreL ausgeführt werden, aber nicht von Java?

Mein erster Gedanke ist, dass Sybase möglicherweise Ausführungspläne für die vorbereiteten Anweisungen zwischenspeichert und den Index nicht verwendet. Wir haben versucht, den Java-Server mehrmals neu zu starten (andere Dienste verwenden den Sybase-Server, so dass es schwieriger ist, zu springen) und es hat keinen Unterschied gemacht.

Die andere Möglichkeit ist, dass wir eine sehr alte Version der Sybase-Treiber verwenden:

jConnect (TM) for JDBC(TM)/7.00(Build 26502)/P/EBF17993/JDK16/Thu Jun 3 3:09:09 2010 

Ist es möglich, dass funktionelle Indizes werden nicht von dieser Version von JConnect unterstützt?

Weiß jemand, ob irgendeine dieser Theorien richtig ist, oder ob es etwas anderes gibt, das ich verpasst habe?

+1

Vielleicht relevant: [Anweisung Cache] (http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc31644.1570/html/sag2/CHDHGEFE.htm) Was genau Version von Sybase hast du? Und sind die Anfragen identisch? (nur eine wilde Vermutung, die Anweisung cache kann Groß-und Kleinschreibung beachten) –

+1

Siehe auch diese Tipps: http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc00967.1550/html /MigrationGuide/MigrationGuide14.htm –

+0

Wie identisch sind die Abfragen von den 'anderen' Systemen gegenüber der Java-basierten Abfrage? Die vorbereitete Aussage kann auch das Problem sein, sind irgendwelche der Werte parametrisiert? Ein guter Test wäre, die identische SQL, die von der Konsole läuft, zu ziehen und sie in eine reguläre JDBC-Anweisung von Java einzufügen und sie "wie sie ist" auszuführen. – rolfl

Antwort

1

Ich habe das in der letzten Woche oder so weiter untersucht und obwohl ich noch keine definitive Antwort habe, habe ich eine plausible Theorie.

Ich habe versucht, die Vorschläge aus den Kommentaren und dank ihnen, dass ich die Sache auf eine einzige Änderung verengen konnte, wenn ich die Abfrage haben:

"where LOWER(aca.l5_codpost) like '"+StringEscapeUtils.escapeSql("NG179GT".toLowerCase())+"'" 

Dann wird die Abfrage den Index und kehrt verwendet extrem schnell.

Wenn auf der anderen Seite habe ich:

where LOWER(aca.l5_codpost) like :postcode 

query.setString("postcode", "NG179GT".toLowerCase()); 

Dann ist es nicht, den Index nicht verwendet.

Die Theorie ist, dass Sybase den Abfrageplan ohne Informationen über den Inhalt von :postcode optimiert, so dass es den Index nicht verwendet. Es kompiliert die Abfrage nicht neu, sobald es den Inhalt kennt, so dass es den Index nie verwendet.

Ich habe versucht, den Index mit (index acadress_codpost_lower) erzwingen und das machte keinen Unterschied.

Ich habe versucht set forceplan off und set literal_autoparam off und keinen Unterschied gemacht.

Das einzige, was ich finden kann, dass das Verhalten ändert, ist die Option direkt in den Abfrageplan einbetten vs als Parameter zu haben.

Also die Arbeit umgibt den Parameter in den Query-String, obwohl ich immer noch gerne wissen möchte, was tatsächlich passiert und das Problem richtig lösen.

Verwandte Themen