Почему Sybase не использует функциональный индекс?

Я создал функциональный индекс для таблицы Sybase.

create index acadress_codpost_lower on acadress(LOWER(l5_codpost))

Затем я запускаю сложный запрос, который использует индекс. Без индекса это занимает 17.086 секунд. С индексом это занимает 0,076 секунды.

Я запускал его на двух разных клиентах SQL, а также на серверах разработки и предварительной разработки Sybase. Во всех случаях вижу ускорение от индекса.

Однако когда мы запускаем идентичный запрос из Java (и я знаю, что он идентичен, так как я зарегистрировал сгенерированный SQL и использовал его непосредственно в клиентах SQL), тогда производительность будет точно такой же, как и до того, как мы добавили индексы.

Какая возможная причина может быть для идентичных запросов SQL, чтобы использовать индекс при запуске из ACE и SQuirreL, но не из Java?

Сначала я подумал, что, возможно, Sybase кэширует планы выполнения для подготовленных операторов и не использует индекс. Мы пытались перезапустить сервер Java несколько раз (другие службы используют сервер Sybase, поэтому отказов труднее), и это не имело никакого значения.

Другая возможность заключается в том, что мы используем очень старую версию драйвера Sybase:

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

Возможно ли, что функциональные индексы не поддерживаются этой версией JConnect?

Кто-нибудь знает, может ли быть правильной какая-либо из этих теорий или есть что-то еще, что я пропустил?

1 ответ

Я изучал это время от времени в течение прошлой недели или около того, и хотя у меня все еще нет окончательного ответа, у меня есть правдоподобная теория.

Я попробовал предложения из комментариев, и благодаря им я смог сузить причину до одного изменения, если у меня есть запрос:

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

Затем запрос использует индекс и возвращается очень быстро.

Если с другой стороны у меня есть:

where LOWER(aca.l5_codpost) like :postcode

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

Тогда он не использует индекс.

Теория заключается в том, что Sybase оптимизирует план запросов без информации о содержимом :postcode, поэтому он не использует индекс. Он не перекомпилирует запрос, когда узнает содержимое, поэтому никогда не использует индекс.

Я пытался заставить индекс с помощью (index acadress_codpost_lower) и это не имело никакого значения.

я пробовал set forceplan off а также set literal_autoparam off и ни один не имел никакого значения.

Единственное, что я могу найти, что изменяет поведение, - это непосредственно встраивать опцию в план запроса по сравнению с ее наличием в качестве параметра.

Поэтому обходной путь - встраивание параметра в строку запроса, хотя я все еще хотел бы знать, что на самом деле происходит, и правильно решить проблему.

Другие вопросы по тегам