#sql #derby
#sql #derby
Вопрос:
я был бы очень признателен за помощь здесь. Я получил эту базу данных derby от моего клиента и их приложения на основе гибернации. Я не могу заставить его работать, потому что Hibernate генерирует запрос, который отключает всю базу данных:
select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from SRG.HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from SRG.STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from SRG.TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555'))
Я не вижу в этом ничего подозрительного, но когда я запускаю derby с его помощью — derby просто ничего не делает. Вот мои журналы:
2011-10-31 21:58:10.328 GMT Thread[DRDAConnThread_3,5,main] (XID = 1152939), (SESSIONID = 1), (DATABASE = dev), (DRDAID = NF000001.FC97-434877518919679629{1}), Begin compiling prepared statement: select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555')) :End prepared statement
2011-10-31 21:58:10.682 GMT Thread[DRDAConnThread_3,5,main] (XID = 1152939), (SESSIONID = 1), (DATABASE = dev), (DRDAID = NF000001.FC97-434877518919679629{1}), End compiling prepared statement: select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from SRG.HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from SRG.STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from SRG.TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555')) :End prepared statement
2011-10-31 21:58:10.758 GMT Thread[DRDAConnThread_3,5,main] (XID = 1152939), (SESSIONID = 1), (DATABASE = dev), (DRDAID = NF000001.FC97-434877518919679629{1}), Executing prepared statement: select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from SRG.HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from SRG.STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from SRG.TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555')) :End prepared statement
И после этого НИЧЕГО.
Я установил некоторые свойства:
derby.drda.portNumber=1529
derby.locks.deadlockTrace=true
derby.locks.monitor=true
derby.locks.deadlockTimeout=1
derby.locks.waitTimeout=1
derby.language.logStatementText=false
derby.infolog.append=true
derby.stream.error.logSeverityLevel=0
derby.drda.logConnections=true
derby.language.logStatementText=true
derby.language.logQueryPlan=true
чтобы увидеть, что происходит, но в журналах ничего нет, выполнение этого запроса занимает целую вечность, либо оно выполняется из hibernate, либо squirrelsql, либо из инструмента ij от derby.
Как вы можете видеть, тайм-ауты довольно малы, но derby не останавливает выполнение запроса, он оставляет его делать все, что хочет запрос.
Запрос не такой сложный — я переписал его с помощью joins, и для выполнения потребовалось 1 сек. Но не в такой форме — я не понимаю, почему? Можете ли вы дать мне какие-либо подсказки?
UPD: house_reference содержит 7508 строк, выбор * из house_reference занимает менее секунды, street_reference содержит ~ 44 тыс. строк, а подзапрос
select streets0_.ID from STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='52000001000')
возвращает 111 строк менее чем за секунду. таким образом, выбор * из house_reference с предложением in, содержащим 111 строк, занимает 22 минуты и возвращает 0 результатов. Для меня это не выглядит нормально, но я не настолько опытен в администрировании баз данных, чтобы судить, поэтому я спрашиваю сообщество 🙂
Ответ №1:
Запросы, указывающие «in (подзапрос)», не всегда могут быть заменены соответствующим соединением. Этот процесс называется «выравнивание», и существуют правила, которым должна следовать база данных, чтобы дать правильный ответ. Смотрите эту документацию: http://db.apache.org/derby/docs/10.8/tuning/ctuntransform36368.html
К сожалению, нередко возникают значительные проблемы с производительностью при выполнении подзапросов в соединениях. Я рад, что вы нашли обходной путь (при условии, что ваш переписанный запрос на самом деле является приемлемым обходным путем для вас).
Библиотеки объектно-реляционных сопоставлений могут генерировать некоторые сложные запросы. Если вы можете заставить запрос в конечном итоге выполняться, вы можете кое-что узнать из плана запроса.
Другая возможность заключается в том, что статистика базы данных стала неточной, в результате чего Derby выбрал плохой план запроса. В последних версиях Derby улучшена поддержка повторного вычисления статистики, что может помочь оптимизатору выбрать лучший план запроса.
В руководстве по настройке Derby по адресу http://db.apache.org/derby/docs/10.8/tuning/index.html
Комментарии:
1. Это не обходной путь, потому что мне не разрешено изменять эту конкретную часть кода клиента. Я переписал его, просто чтобы проверить, все ли в порядке с таблицами, и они не слишком большие. Я спрашиваю: почему derby не останавливает этот запрос после тайм-аута? почему он не записывает план выполнения в файл журнала? почему derby ничего не делает с этим во время выполнения?
2. Я не уверен. Какой тайм-аут вы имеете в виду? derby.locks.deadlockTimeout и derby.locks.waitTimeout имеют отношение к управлению параллелизмом между независимыми транзакциями, А НЕ к остановке выполнения запроса, выполнение которого занимает много времени.
3. Ох. Это единственные тайм-ауты, которые я установил до сих пор. Это имеет некоторый смысл, но время выполнения действительно огромно.