| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Базы данных и репортинг > Медленно работает |
| Автор: MihailCarib 15.11.2010, 21:48 | ||
Здравствуйте! Работаю с БД Access через ADO. Данные получаю в таблицу с внешнего носителя. Вид данных - сильно замусоренные. Для фильтрации ввожу линейный фильтр с окном по 10 значениям, паолученные данные кидаю в другую табличку в той же базе. Обе таблички работают на разных ADOConnection DBGrid не подключен. Все работает, но получается, что 2-2,5 тысячи записей он обсчитывает крайне медленно. Работать с массивом гораздо быстрее, но опять-таки, в массив данные из БД еще надо записать, а это секунд 5, не меньше. В то же время, простой Excel делает все так, что заметить не успеваешь. Как мой код можно оптимизировать, что я делаю не так? Привожу пример функции
Спасибо! |
| Автор: CROTishka 16.11.2010, 09:40 |
| Мало того, что ваши данные можно получить без всяких временных таблиц одним скулёвым запросом, так ещё и непонятно зачем вы через запросы данные в ADOQuery3 пихаете. Советую переделать добавление так так: http://msdn.microsoft.com/en-us/library/ms677536(VS.85).aspx . Ещё очень много съедает локейт. Используйте TDataSet.Next/Prior + ORDER BY или TCustomADODataSet.Sort. В общем учитесь. |
| Автор: MihailCarib 16.11.2010, 18:15 |
| О, то, что нужно. Спасибо. Буду познавать. Честно говоря, считал, что локейт быстрее... Только вот не понятно, каким таким хитрым SQL запросом можно решить сразу всю задачку? |
| Автор: CROTishka 16.11.2010, 18:41 | ||
самое банальное, но не очень оптимальное:
возможно можно как-то с окнами извратится, или через курсор сделать, чтобы быстрее работало - я привык уже к различным расширениям SQL |
| Автор: MihailCarib 16.11.2010, 19:43 |
| А, я понял. Сделать запрос на вычисления одного окна - не проблема. Проблема сдвинуть это окно, ну уж это ладно. Проверил - first/next действительно быстрее Locate, правда не на много, но по копеечке набегает. А запись мне все равно в другую табличку делать, потому как в конце все данные (с обработкой и без) подключаются к DBChart по желанию пользователя, значит их по-любому где-то хранить. Вы мне вот еще что подскажите- буду очень признателен, а нет ли возможности кинуть в DBChart сразу массив данных, не забирая их поэлементно? Признаюсь, ранее я работал с БД очень мало, в основном с BDE и задачи такие не ставились, объем информации перелопатить сразу очень большой тяжко, Вы мне хоть направления обозначьте. Спасибо! |
| Автор: superVad 16.11.2010, 20:22 | ||
MihailCarib, ты количество записей вычисляешь до открытия таблицы.
Не знаю есть ли в этом ошибка (таблица могла быть и до этого открыта), но как то не правильно. |
| Автор: MihailCarib 16.11.2010, 21:10 |
| Спасибо. Таблица открывается ранее, но ошибка быть могла. Исправлю. |
| Автор: CROTishka 17.11.2010, 09:33 | ||||
что мешает вам хранить их в рекордсете/датасете?
TChartSeries.AddArray() |
| Автор: MihailCarib 30.11.2010, 21:16 |
| Все попробовал. Ысе заработало, спасибо! Выяснилось, что запрос на добавление записи 'INSERT INTO '+IntToStr(Card_num) и т.д. конструкция form8.ADOQuery1.Insert; form8.ADOQuery1.FieldByName('№').AsInteger:= а также form8.ADOQuery1.recordset.AddNew(field,value); работают примерно одинаково по времени, и для меня неприемлемо медленно. Как делаю: есть цикл на чтение данных, данных много, 10000 строк - это норма, инфа читается с флешки. В этом цикле после чтения блока данных построчно добавляю информацию в базу, и это не катит по скорости записи. Вопрос, как подобные задачи решают нормальные программисты? Скорость чтения с флешки бешеная, все тормозит именно запись в базу. Куда мне лучше (быстрее) заносить данные во время чтения флешки и как их потом быстро скопом перекидывать в базу? |
| Автор: CROTishka 1.12.2010, 15:21 |
| ну добавляйте не построчно, а скопом/блоками, если оперативки хватит в чём проблема? триггеры на инсерт у вас не стоят? существенно ускорить процесс поможет только смена БД на нереляционную. |
| Автор: MihailCarib 1.12.2010, 22:39 |
| Стоп стоп стоп, не так быстро! Я же все-таки чайник, причем кипящий. Добавлять скопом как? Писать все в массив/файл, а дальше ADOQuery1.recordset.AddNew(field,value); в value вносить этот массив? Можно примерчик, маленький? Триггеры на инсерт не стоят, если я правильно понимаю, это счетчики количества записей в самой базе, я их отключил. Но в цикле есть необходимость крутить переменную, я ее использую в качестве поля номера строки. Не очень оптимально, но я отключал это дело, совсем копеечки по производительности. Вот теперь самое интересное. Программа работала раньше через BDE на таблицах Paradox и все было не сказать что шустро очень, но меня устраивало. Потом оказалось нужно, чтобы все работало без BDE и единственный удачный пример на тот момент я нашел под Access. Access мне использовать удобно, но я был не в курсе таких проблем, как скорость записи/чтения и прочие "мелочи". А теперь эти "мелочи" меня дрючат, но опыта чуток прибавилось, возможно осилю чего другое. Посоветуйте, с чем сейчас стОит поработать, чтобы пошустрее было? |
| Автор: CROTishka 2.12.2010, 09:55 |
| Для начала научитесь использовать http://lmgtfy.com/?q=%D0%A2%D1%80%D0%B8%D0%B3%D0%B3%D0%B5%D1%80+(%D0%B1%D0%B0%D0%B7%D1%8B+%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85), прежде чем писать всякую фигню. Во вторых конечно стоит научиться использовать документацию: http://msdn.microsoft.com/en-us/library/aa933206(SQL.80).aspx И в третьих, хотя бы отдалённо разобраться в том, как работает то, что вы делаете. (Почитайте хотя бы встроенный хелп - встать на метод, Ctrl+F1) В четвертых, если хотите помощи, то стоит писать нормально по схеме: "что делаете (ПОДРОБНО), что хотите, что на самом деле получается." Иначе помогать никто вам не будет. (У меня сегодня просто ангельское настроение и терпение) |
| Автор: MihailCarib 2.12.2010, 21:16 | ||
| Уважаемый CROTishka! Огромное Вам спасибо, за ангельское настроение и терпение! Смею Вас заверить, что в тех областях, в которых я являюсь специалистом, я также, как Вы, на профильных форумах делаю такие приписки, за что меня очень ценят и хотят спрашивать еще и еще. Поймите, познать все и сразу невозможно, у меня две вышки, диссер, куча дипломов и пр., но при этом я НЕ УМЕЮ программировать. Пока. Но хочу научиться, не потому, что денег нет, а потому что интересно. Времени на изучение мне никто не выделяет, все факультативно. Поэтому, не ругайтесь на новичка, пожалуйста. За ссылку на MSDN спасибо, про F1 тоже вовремя, но все это я читал, и мои вопросы остались нерешенными. Код привести полностью не могу (мне не жалко, просто он большой), процедура такая:
В чем проблема: я кручу в цикле обращение к карте ReadFile(hdevice, field, 512, cb, nil); и тут же в цикле открываю таблицу и делаю запись ADOQuery1.FieldByName('Z').AsFloat:=Z; Это не правильно и долго! Мне бы хотелось, чтобы в цикле было только обращение к карте и запись , скажем в файл - это будет быстрее, а после цикла в отдельной процедуре вносить данные из файла в базу. Все примеры, которые мне удалось найти, вносят в базу данные построчно, т.е. так, как это делал я в приведенном коде, либо при помощи ADOQuery1.recordset.AddNew, как описано тут http://msdn.microsoft.com/en-us/library/ms677536(v=VS.85).aspx Спасибо. |
| Автор: CROTishka 3.12.2010, 10:04 |
| Конечно неправильно. Пользоваться активным подключением к бд вообще не правильно. Используйте TADOCommand и изучайте SQL. Ссылку на инсерт я вам дал. Еще обычно интерфейсную часть тоже показывают. |
| Автор: MihailCarib 3.12.2010, 21:36 |
| Ок, спасибо,буду постигать. |