16:09

Никогда не доверяй собаке с оранжевыми бровями.
Здравствуйте, хочу посоветоваться.
Несколько лет успешно программировала мелкие проги, а тут понадобилась более объемная, и очень не хвататет теоретических знаний.
Java в среде NetBeans, JDBC.
Сама программа довольно простая, есть таблица в базе где-то на 100 тыс строк, и нужно проверить сочетания всех строк по некоей математической формуле, и выбрать наиболее подходящее сочетания по определенным требованиям. Со всем этим я справилась, но процесс занимает слишком много времени. Добавила многопоточность, все равно слишком долго. Как вообще обычно решают подобные вопросы, может подходящее железо поможет? В нем я вообще ничего не смыслю.

@темы: Вопрос, База данных, Computer Science, Java

Комментарии
22.08.2016 в 16:55

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

Может быть есть какие-то возможности из математических соображений сузить изначальную выборку и перебирать не все сочетания?
Если формула одна и та же, новые строки добавляются редко - тогда можно в базе же кэшировать результаты, выполняя какие-то вычисления только при появлении новых строк/изменении старых, а не считать каждый раз. Если формул фиксированный набор, то аналогично.
Ну и у вас еще могут быть проседания по производительности, если делаете много мелких запросов в базу вместо нескольких больших.
22.08.2016 в 22:27

Первым делом надо выяснить, что именно тормозит. Честно измерить. Если запрос к базе, надо ускорять его. Например, ввести индексы.
23.08.2016 в 13:07

Никогда не доверяй собаке с оранжевыми бровями.
Большое спасибо ответившим.
Reflendey,
Сочетания всех строк при таком количестве, даже если вы имели ввиду пары, это очень много.
Да, именно пары.
Если формула одна и та же, новые строки добавляются редко - тогда можно в базе же кэшировать результаты
Не вполне одна, но возможно получится сохранить элементы. Спасибо, я погуглю как это делать.
Ну и у вас еще могут быть проседания по производительности, если делаете много мелких запросов в базу вместо нескольких больших.

Возможно, у меня каждое сочетание двух строк запускается отдельным потоком, и в нем уже идет запрос. А можно запросить все данные скопом, а потом в отдельных потоках вычленить нужные строки без использования sql query?

8115,
Индексы есть, все равно медленно. Но, кажется, тормозят именно запросы.
23.08.2016 в 14:02

Reflendey
Возможно, у меня каждое сочетание двух строк запускается отдельным потоком, и в нем уже идет запрос.
То есть вы создаете новый поток на каждый запрос?
Не очень понятно даже как он должен выглядеть
Т.е. для меня (я если что не настоящий сварщик, с БД дел практически не имею), вообще не очень ясно как можно разбить условно такой запрос
;
на N запросов. Ну кроме как явно указывая id. В общем это кажется весьма неэффективным способом, если я правильно понял что вы делаете.

А можно запросить все данные скопом, а потом в отдельных потоках вычленить нужные строки без использования sql query
Да что-то вроде
stackoverflow.com/questions/984073/java-jdbc-la... вот примерно как тут написано. В главном потоке кладете в очередь следующее значение, а в остальных потоках из этой очереди берете результаты и обрабатываете.
Я бы как-то так попробовал.
23.08.2016 в 20:45

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Спасибо, вы очень помогли, буду копать в эту сторону.
24.08.2016 в 23:22

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Воспользовалась последним способом, отлично работает, намного быстрее. Но только на пробных партиях с меньшим количеством потоков, а когда запускаю основную, где каждая пара строк отдельным потоком, то в лучшем случае падает соединение с дерби, а в худшем - виснет весь комп. Не знаете что можно с этим сделать?
24.08.2016 в 23:44

Reflendey
Lazurit,
Так нет никакого смысла делать число потоков больше чем число ядер на компьютере (когда смысл создания потоков исключительно в производительности за счет параллельного исполнения, как в вашем случае). На создания потока тоже ресурсы уходят, поэтому и подвисает в итоге.
Сделайте например сразу 4 потока, и в каждом запустите функцию, которая достает элементы из очереди и обрабатывает их пока очередь не опустеет.
25.08.2016 в 00:10

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Да, сама уже это нагуглила и расстроилась-_- Придется переписывать и подбирать другие варианты.
26.08.2016 в 19:43

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Простите, что гружу вас)
Наладила 8 потоков по числу ядер. Теперь самым тормозящим элементом остались многочисленные запросы из таблицы. Решила попытаться кэшировать, каждый запрос используется по несколько сотен раз. Можно ли кэшировать резалтсет целиком?
Для кэширования использовала класс:
26.08.2016 в 20:22

Reflendey
Lazurit,
Немного не понял, откуда взялись многочисленные, мне казалось вы в итоге сделали с 1 запросом. Или остальные нужные уже потом для самих математических функций?
Или многочисленные в том смысле, что при вводе пользователем каждой новой функции надо опять заного считывать?

Можно ли кэшировать резалтсет целиком?
Теоретически-то конечно можно, но на деле я так прикинул размерность, если у вас 100 тысяч строк и вы рассматриваете все пары, а одна строка 10 байт скажем (а скорее всего все-таки больше), то вроде как порядка 45гигабайт занимает это.
Столько оперативной памяти у вас скорее всего нет, так что вариант отпадает. Можно конечно сериализовать попробовать это на диск, но честно говоря, не представляю даст ли это какое-то ощутимое ускорение по сравнению с генерированием из БД на лету.
26.08.2016 в 20:40

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Нет, функция одна. Но для каждой новой пары нужно брать данные из другой таблицы, то есть для каждой пары есть два запроса. Грустно выходит.
Теоретически-то конечно можно, но на деле я так прикинул размерность, если у вас 100 тысяч строк и вы рассматриваете все пары, а одна строка 10 байт скажем (а скорее всего все-таки больше), то вроде как порядка 45гигабайт занимает это.
У меня не совсем 100 тысяч срок. Там скорее 1200 строк, но на каждую пару этих срок нужно брать пару запросов из другой таблицы, она как раз на 100 тыс.
А как вообще обычно решаются подобные проблемы? Вроде же переборы из больших баз много где делаются. Я в принципе могу получить для обработки время на кластере, но я понятия не имею как под него писать и можно ли сперва проверить программу в домашних условиях.
26.08.2016 в 20:57

Reflendey
для каждой новой пары нужно брать данные из другой таблицы, то есть для каждой пары есть два запроса.
Это возможно опять же сделать одним SQL запросом. Собственно SQL для того и нужен, чтобы делать такие запросы, он конечно будет большой и страшный, но это нормально.
Заодно субд сама вам все и кеширует в процессе выполнения, чтобы несколько раз одно и тоже не считывать. В любом случае быстрее будет делать все по максимуму на стороне субд, они для того и придуманы)


У меня не совсем 100 тысяч срок. Там скорее 1200 строк, но на каждую пару этих срок нужно брать пару запросов из другой таблицы, она как раз на 100 тыс.

Тогда точно можно без кластера обойтись, да и кэшировать все целиком возможно на современном компьютере, однако просто все-таки впихнуть все в один запрос, мне кажется лучше.
26.08.2016 в 21:58

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Тогда точно можно без кластера обойтись, да и кэшировать все целиком возможно на современном компьютере, однако просто все-таки впихнуть все в один запрос, мне кажется лучше.
То есть, кэшировать всю таблицу? А как тогда указать программе, что берешь запрос именно из кэша СУБД, а не просто из таблицы?
26.08.2016 в 23:17

Reflendey
Lazurit,
А как тогда указать программе, что берешь запрос именно из кэша СУБД, а не просто из таблицы?
Как я уже говорил, я не настоящий сварщик. Если вы делаете все одним запросом, то заботится извне вообще ни о чем не надо, субд сама все отпимизирует.


Если же вы хотите все-таки делать много запросов, то это "как тогда указать программе, что берешь запрос именно из кэша СУБД" зависит от субд. У вас вероятно не оракловая субд, да и ссылка не кажется свежей, но для примера docs.oracle.com/cd/B10501_01/java.920/a96654/st....
27.08.2016 в 12:06

Никогда не доверяй собаке с оранжевыми бровями.
Reflendey,
Вы все равно явно опытнее меня) Спасибо за ссылку, буду учиться. Оракловая, кажется, нетбинс же.