Я использую Java 1.6, JTDS 1.2.2 (также просто попробовал 1.2.4 безрезультатно) и SQL Server 2005 для создания CallableStatement для запуска хранимой процедуры (без параметров). Я вижу, что оболочка Java работает с той же самой хранимой процедурой на 30% медленнее, чем с помощью SQL Server Management Studio. Я запускаю профилировщик MS SQL, и между этими двумя процессами разница между вводами и выводами невелика, поэтому я не думаю, что это связано с кэшированием плана запроса.
Хранимый proc не принимает аргументов и не возвращает никаких данных. Он использует серверный курсор для вычисления значений, необходимых для заполнения таблицы.
Я не вижу, как вызов хранимого proc с Java должен добавить 30% накладных расходов, конечно же, это просто канал базы данных, который отправлен SQL, а затем база данных выполняет его. Может ли база данных быть давая Java-приложению другой план запроса?
Я опубликовал как форумы MSDN, так и форумы sourceforge JTDS (тема: "хранимый процесс медленнее в JTDS, чем прямой в DB" ) Мне было интересно, есть ли у кого-нибудь какие-либо предложения относительно того, почему это может произойти?
Спасибо заранее,
-Джеймс
(N.B. Не бойся, я буду сопоставлять любые ответы, которые я получаю на других форумах вместе, как только найду решение)
фрагмент кода Java:
sLogger.info("Preparing call...");
stmt = mCon.prepareCall("SP_WB200_POPULATE_TABLE_limited_rows");
sLogger.info("Call prepared. Executing procedure...");
stmt.executeQuery();
sLogger.info("Procedure complete.");
Я запустил sql-профайлер и нашел следующее:
Java-приложение: CPU: 466,514 Считывает: 142,478,387 Пишет: 284 078 Продолжительность: 983,796
SSMS: CPU: 466,973 Считывает: 142,440,401 Пишет: 280,244 Продолжительность: 769 851
(Оба с DBCC DROPCLEANBUFFERS работают до профилирования, и оба создают правильное количество строк)
Итак, я заключил, что они оба выполняют одни и те же чтения и записи, просто так, как они это делают, разные, что вы, ребята, думаете?
Оказывается, что планы запросов существенно различаются для разных клиентов (клиент Java обновляет индекс во время вставки, который не находится в более быстром SQL-клиенте, также, как он выполняет объединения, отличается (вложенные петли Vs. собирать потоки, вложенные циклы Vs index scans, argh!)). Вполне возможно, что я еще не знаю (я буду переписывать, когда дойду до конца)
Эпилог
Я не мог заставить это работать правильно. Я попытался гомогенизировать свойства соединения (arithabort
, ansi_nulls
и т.д.) Между студентами студии Java и Mgmt. В итоге у двух разных клиентов были очень похожие планы запросов/выполнения (но все же с разными фактическими плагинами). Я опубликовал сводку того, что я нашел в форумах MSDN SQL Server, поскольку я нашел отличную производительность не только между клиентом JDBC и студией управления, но также между клиентом командной строки Microsoft, SQLCMD, я также проверил некоторые более радикальные вещи, такие как сетевой трафик, или обернул хранимый процесс внутри другого хранимого proc, просто для усмешек.
У меня есть ощущение, что проблема кроется где-то в том, как выполняется курсор, и это каким-то образом приводит к приостановке процесса Java, но почему другой клиент должен вызвать это другое поведение блокировки/ожидания, когда ничего else работает, и один и тот же план выполнения находится в процессе немного выше моих навыков (я не DBA!).
В результате я решил, что на 4 дня хватит времени на то, чтобы тратить время на что-то подобное, поэтому я буду неохотно координировать его (если честно, хранимая процедура требует повторного кодирования, чтобы быть более инкрементальным вместо того, чтобы каждый раз пересчитывать все данные каждую неделю), а также мелом, чтобы это произошло. Я оставлю вопрос открытым, большое спасибо всем, кто положил шляпу на ринг, все было полезно, и если кто-нибудь придумает что-нибудь еще, я бы хотел услышать еще несколько вариантов... и если кто-нибудь найдет этот пост в результате наблюдения этого поведения в их собственных средах, то, надеюсь, здесь есть несколько указателей, в которых вы можете попробовать себя, и надеяться, что мы полностью увидим дальше, чем мы.
Я готов на выходные!
-Джеймс