Реализацията на DB2 JDBC има ли проблеми с оптимизирането на подизбор?

?Имаме уеб приложение, изпълняващо заявка, използваща JDBC с DB2 Universal JDBC драйвер (v9.7).
Изпълнението на заявката отнема поне 2 минути, когато се изпълнява през приложението. В командния ред обаче същата заявка отнема само две секунди. Не можем да разберем къде е проблемът.

WebSphere AppServer седи зад прокси сървър WebSEAL, който има изчакване от 2 минути, така че когато на приложението са необходими повече от 2 минути, за да отговори, потребителите виждат грешка. Потребителите съвсем наскоро съобщиха за проблема, но не са направени скорошни промени. Подозирам, че времето за отговор на заявката постепенно нараства и накрая достигна времето за изчакване на WebSEAL.

Заявката има подизбор в клаузата WHERE (която трябва да се изпълни само веднъж) и се чудя дали този подизбор не е оптимизиран при преминаване през JDBC, което го кара да се изпълнява отново с всеки ред от обединените таблици.

Запитването е:

SELECT A.VOIDED, A. DELIVERY_DATE_TEXT, A.TRANSACTION_ID, A.AIRBILL_NUMBER, A.NAME, B.DOCUMENT_NUMBER, B.STATUS 
FROM SHIPPING A, TRANSACTION B 
WHERE A.TRANSACTION_ID = B.TRANSACTION_ID 
  AND A.ORIGINAL_REQUEST_TIME < 
     (SELECT ORIGINAL_REQUEST_TIME FROM SHIPPING WHERE AIRBILL_NUMBER = ?) 
  AND B.STATUS <> 4 
  AND A.VOIDED IS NULL

Таблицата TRANSACTION има 1,8 милиона записа в нея, а таблицата SHIPPING има 95 000.

Има ли нещо нередно в заявката? Работи добре в CLI.
Или има грешка в DB2 JDBC драйвера?


Актуализация:

Е, опитахме програма за тестване на командния ред (без Websphere) с директна връзка (вместо набор от връзки) и без обвиващ обект на Spring JDBC (който използваме в приложението) и проблемът не можа да бъде пресъздаден.

След това използвахме db2expln, за да разгледаме плановете на заявката за заявката със и без параметъра и те бяха еднакви във всеки случай.

НАЙ-НАКРАЯ успяхме да изпробваме runstats на производствената маса и това направи разликата. Заявката за приложението се връща след няколко секунди сега. Фактът, че помогна, беше неочакван. Първоначално не го бяхме правили, тъй като CL заявката беше толкова бърза.

Така че предполагам, че проблемът е решен. Но все още не знаем защо заявката за Websphere JDBC първоначално беше толкова по-бавна от заявката от командния ред (и заявката за JDBC, която не е Websphere).


person Todd Phillips    schedule 31.03.2014    source източник
comment
Вероятно JDBC не е проблемът тук, а по-скоро има някаква друга разлика. Сигурни ли сте, че уеб приложението предоставя действителни стойности за AIRBILL_NUMBER и STATUS, или използва маркери за параметри?   -  person Ian Bjorhovde    schedule 31.03.2014
comment
B.STATUS ‹› 4 е твърдо кодиран в заявката. AIRBILL_NUMBER е единственият параметър. Заявката работи: понякога отговорът ще бъде върнат малко под стойността на времето за изчакване и върнатите данни са правилни, но това е рядко и продължава да отнема твърде много време. Същият код работи добре в нашата тестова среда, но размерът на таблицата е много по-малък. Тази заявка и свързаният с нея код работят от години и подозирам, че комбинация от размера на таблицата и версията на JDBC драйвера е отговорна за бавния отговор, който виждаме сега.   -  person Todd Phillips    schedule 31.03.2014
comment
Може да искате да сравните плановете на заявката, генерирани за заявката: едната с маркера на параметъра, а другата с литерала. Опитайте да актуализирате статистиката на таблицата SHIPPING с разпределение.   -  person mustaccio    schedule 31.03.2014
comment
Проблемът е решен с runstats. Вижте актуализацията по-горе.   -  person Todd Phillips    schedule 01.04.2014
comment
Колегата намери това, което изглежда същото или много подобно: dbforums.com/db2/   -  person dbreaux    schedule 02.04.2014


Отговори (1)


Почти със сигурност разликата в този случай е, че подадената JDBC заявка използва маркер за параметър, докато заявката, която изпълнявате на командния ред, има всички стойности, показани изрично.

С изричната стойност DB2 може да използва статистика за разпространение, за да компилира заявката, което вероятно води до по-ефективен план за заявка. Както предлага @mustaccio, трябва да сравните плановете на заявките между 2-та варианта на заявката, за да видите какво DB2 прави по различен начин между тях.

person Ian Bjorhovde    schedule 31.03.2014
comment
Приблизителната стойност на разходите (44770) и графиката на плана на заявката (върната от db2expln) са едни и същи със и без маркера на параметъра. - person Todd Phillips; 01.04.2014