| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Базы данных и репортинг > ODAC |
| Автор: AndreyZ53 13.1.2015, 19:08 |
| Доброго времени суток. Для доступа к oraсle использую компоненты odaс. Вопрос заключается в том, что когда делаю запрос, то приложение зависает, так как в базе миллионы записей и пока найдет нужную, то проходит порядка 12 минут. Это дело понятное. Данный вопрос я решил, установив свойство nonbloсking компонента TOraQuery в True и добавил анимацию. Теперь запрос выполняется в отдельном потоке, приложение не виснет, а при помощи анимации (бегунок), пользователь видит, что приложение не зависло и что-то ищет. Но теперь вопрос вот в чем, если там из 10 миллиона записей нашло 100 тысяч, то в dbgrid (у меня грид с ehlib 3.6, бесплатной версии), то он отображает по 25-50 записей, начинаю прокручивать грид, приложение опять зависает, чтобы отобразить следующие 25-50 записей на минут 5, но уже именно зависает. А как мне можно сделать и тут, чтобы оно не зависало и появлялась анимация, что оно ищет остальные записи, может кто подскажет? |
| Автор: AndreyZ53 13.1.2015, 20:34 |
| Vas, спасибо за ответ. Насчет индексов ничего не могу сказать, но клиент sqldeveloper, через который я работаю с базой и таблицами, запрос примерно также делает. База не моя, существует уже много лет, как пришел на работу, она уже стояла там с 2007 года, каждый месяц в нее добавляется по 350-400 тысяч записей. Использую именно OraQuery, я с odaс не так давно работаю, еще мало про него знаю. Индекса конечно есть в базе, но я с ораклом как-то не очень, база есть, подключился, просто хочу для себя написать приложение небольшое, чтобы оно выводило мне набор записей за день по определенному условию, а не каждый раз я бы подключался к oraсle через sqldeveloper и что-то там делал. Может подскажите как ускорить процесс запроса. В базу лезть я не хочу, так как там много разных триггеров, процедур и так далее. Был у нас человек, который администрировал БД, его на курсы отправляли, но он уволился, предприятие сейчас не хочет отправлять человека и платить деньги за обучение. Поэтому лезть туда не хочу, если что-то не так сделаю, то станет основная деятельность предприятия. А я хочу мини-программку для себя сделать, вывелись записи, я произвел с ними небольшие действия, распечатала данные и все. Но программку тоже хочу сделать не абы как. Потому что ставить буду нескольким сотрудникам. А то они начнут прокручивать или долго запрос делаться, то подумают, что не работает и все, начнут через процесс завершать. В OraQuery выставил 1000 записей чтобы выводило, но может можно как-то ускорить быстроту выполнения запроса в многомиллионной БД? |
| Автор: Vas 13.1.2015, 20:58 | ||
Это вопрос в профильный раздел форума "Базы данных" там быстрее помогут. |
| Автор: superVad 14.1.2015, 10:41 |
| AndreyZ53, выход из этого - расположить над гридом фильтр и по какой то кнопке отображать записи. Если условия не выбраны, то предупреждать, что это будет долго. Было подобное у меня, пока вышли из положения таким образом, что при входе в программу показываются записи за последний месяц (фильтр так установлен). Никому не надо 100 тыс. записей в гриде. |
| Автор: AndreyZ53 14.1.2015, 10:54 | ||
| superVad, что-то я не могу сообразить, подскажите еще пожалуйста. При открытии формы у меня стоит выполнение запроса.
Отображается 25 записей у меня сразу же, так как в свойстве FetchRows компонента TOraQuery стоит 25. Почему-то фильтр не срабатывает сразу, выводит все записи, то есть, ТИП 29 он игнорирует. Начинаю пролистывать грид, и чтобы он отобразил следующие 25 записей, приложение просто зависает, как этого избежать? Точнее оно зависает, если я резко бегунок прокрутки грида опускаю вниз, если понемного опускаю, то появляются новые записи без зависания, но если резко, то приложение зависает и думают, через некоторое время отвисает и показывает следующие записи |
| Автор: superVad 14.1.2015, 13:58 | ||||
| AndreyZ53, на таких количествах записей, возможно стоит отказаться от родной фильтрации компонента. У меня на основе установленных фильтров формируется соответствующий SQL-запрос. Т.е.
Добавлено через 2 минуты и 12 секунд Ну и каждый раз при изменении фильтрации набор данных закрывается, переформируется запрос и набор данных открывается. Это все можно оформить как одну функцию, что бы она срабатывала и при открытии программы и при изменении условий фильтрации. Добавлено через 4 минуты Ну и насчет того почему игнорирует TYP=29. Может попробовать так:
|
| Автор: Vas 14.1.2015, 20:11 | ||||
| Я в таких случаях открываю окно с пустым гридом, над гридом есть панелька с выбором каких то диапазонов или значений фильтров и кнопка выполнить. Причем компоненты фильтрации пустые. так что если просто нажать кнопку выполнить то будет тянуться все из грида P.S. Но из десятков миллионов записей запрос 12 минут для оракуля это не просто дофига, а ужас как дофига для простого запроса с условием и связыванием 1-2 таблиц. Так что сначала оптимизация БД, а потом уже реализация в программе, а то глядишь оно и так сразу залетает у него Добавлено через 2 минуты и 33 секунды
В таком режиме у вас не TOraQuery, а TOraTable. Как я и думал у вас все миллионы тянутся по сети на ваш комп или пользователя, а потом в памяти фильтруется (ужас блин RTFM SQL для чайников причем срочно. |
| Автор: AndreyZ53 28.1.2015, 11:21 |
| Vas, Так а пример небольшой можно, как правильно TOraquery пользоваться, либо ссылочку на литературку. |
| Автор: Vas 28.1.2015, 21:13 | ||
Вот же пример, который superVad привел в своем сообщении, осмелюсь продублировать
Если его выполнить, то выберутся только записи с TYP=29, причем их выберет сервер и передаст ТОЛЬКО ИХ клиенту, тем самым не будет по сети лететь вся таблица, что существенно сократит расходы времени на передачу данных по сети. Соответсвенно делаем вывод, что для OraQuery не надо никаких локальных фильтров, надо просто сформировать запрос с условием и отдать его серверу на выполнение, сервер выберет записи соответствующие нашему условию и вернет их нам. P.S. Для начала надо изучить диалект SQL и тогда понимание запросов и работы с ними само придет. |
| Автор: AndreyZ53 29.1.2015, 08:41 | ||
Vas, Спасибо за разъяснения, у меня сейчас запрос выполняется именно с условием. Но допустим, пользователю прилетела табличка из 200 записей с условием WHERE TYP=29. А ему необходимо из 200, найти быстро запись, допустим по фамилии, тогда же уже необходимо будет применять локальный фильтр, правильно? без него же никак? Но вот с локальным фильтром не могу разобраться, что-то он у меня не работает.
Поле ID_MAIL в базе имеет тип VARCHAR, может я фильтр не правильно указываю? И еще такой вопросик в тему: вот запрос выполняется, пусть минуты 3, а можно ли мне его корректно завершить, чтобы не было никаких ошибок. Грубо говоря остановить его и например запустить опять, чтобы все было корректно? Или как мне использовать этот запрос для нового SQL-оператора. Я сделал SELECT, мне сервер вернул записи, а потом я делаю SQL.Clear для этого запроса, пишу новый, но мне уже выкидывает ошибку: |
| Автор: ТоляМБА 29.1.2015, 15:28 | ||
Если запрос на Select, то сомневаюсь что его можно как-то завершить. Если же запрос на Insert / Update / Delete почитайте о транзакциях. |
| Автор: AndreyZ53 29.1.2015, 15:45 |
| ТоляМБА, Жаль конечно, может можно как-то на уровне OCI это сделать? Просто дело в том, что у меня есть OraQuery, я выполняю SELECT, мне сервер вернул записи, по сути запрос выполнился. Затем я хочу написать другой запрос, но в том же OraQuery, а мне выдает ошибку, которую я прикрепил выше! |
| Автор: ТоляМБА 29.1.2015, 16:11 |
| Перед OraQuery1.SQL.Clear; OraQuery1.SQL.Add(... неплохо бы сделать OraQuery1.Active:=false; то есть закрыть действующий запрос. |
| Автор: AndreyZ53 29.1.2015, 16:30 | ||
я делал:
И делал OraQuery.BreakExec, не помогает, не могу использовать тот же самый OraQuery для другого SELECT, не могу понять почему |
| Автор: ТоляМБА 29.1.2015, 16:54 | ||
AndreyZ53, попробуй этот же запрос выполнить на OraQuery2
И два совета: 1. Вместо +''''+DateToStr(myDate)+''' можно использовать +QuotedStr(DateToStr(myDate))+ 2. Вместо and MAIL.TYP>=29 and MAIL.TYP<=34 можно тоже использовать Between |
| Автор: AndreyZ53 29.1.2015, 17:16 |
| ТоляМБА, В другом OraQuery выполняется норм запрос, но у меня один Dbgrid, в котором и нужно отображать различные данные. Я думаю к DataSource подключать разные OraQuery не совсем правильно будет! |
| Автор: superVad 29.1.2015, 17:25 | ||
Еще можно использовать параметры. |
| Автор: AndreyZ53 30.1.2015, 10:36 |
| superVad, ТоляМБА, Спасибо за дополнения и разъяснения, но может знает, почему я не могу использовать один и тот же OraQuery для разных запросов. OraSession у меня одна, может там что с транзакциями надо делать, типа закрывать их. Не совсем все понятно! |
| Автор: Vas 31.1.2015, 16:09 | ||
| Никогда проблем с выполнением разных запросов в одном OraQuery не было. Вот разные процедуры используют один и тот же OraQuery для выполнения разных запросов
Очищаем, добавляем текст запроса, выполняем, делаем манипуляции, закрываем. Код не весь, часть блоко выкинута и заменена "..." |
| Автор: AndreyZ53 11.2.2015, 11:17 | ||||
Vas, я делаю почти тоже самое, только запрос у меня записан в самом компоненте. Вот:
У компонента выставлены свойства AutoCommit и AutoClose в True, на одну кнопку стоит такой код:
Когда запрос выполнился, я нажимаю на другую кнопку, на которую передаются другие параметры, но приложение просто виснет. Может еще что-то надо выставить в компоненте OraQuery, как настройки и свойства |
| Автор: Vas 11.2.2015, 14:28 | ||
| Open для конструкций SELECT Execute для конструкций INSERT, UPDATE, DELETE Закрывайте открытый запрос перед передачей других параметров
|
| Автор: AndreyZ53 17.2.2015, 09:08 |
| Vas, Делаю как Вы написали, вот такой вот эррор: |
| Автор: salik 17.2.2015, 13:00 | ||
Для начала попробуйте разобраться на какой именно строчке кода выходит ошибка. |