Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Медленно работает, Фильтрация очень медленная 
:(
    Опции темы
MihailCarib
Дата 15.11.2010, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



Здравствуйте! Работаю с БД Access через ADO. Данные получаю в таблицу с внешнего носителя. Вид данных - сильно замусоренные. Для фильтрации ввожу линейный фильтр с окном по 10 значениям, паолученные данные кидаю в другую табличку в той же базе. Обе таблички работают на разных ADOConnection DBGrid не подключен. Все работает, но получается, что 2-2,5 тысячи записей он обсчитывает крайне медленно. Работать с массивом гораздо быстрее, но опять-таки, в массив данные из БД еще надо записать, а это секунд 5, не меньше. В то же время, простой Excel делает все так, что заметить не успеваешь. Как мой код можно оптимизировать, что я делаю не так? Привожу пример функции
Код

procedure Filter(Sender: TObject);
var i,j,records:integer;
sum_X,sum_Y,sum_Z,sum_A:real;
begin
Screen.Cursor:=crHourGlass;
records:= Form8.ADOQuery1.RecordCount; //первоначально записей в базе

//все хранится в базе filter
// трем базу
    try
      Zapros:='DELETE * FROM Filter';
      form8.ADOQuery2.SQL.Clear;
      form8.ADOQuery2.SQL.Add(Zapros);
      form8.ADOQuery2.ExecSQL;

      Zapros:= 'SELECT * FROM Filter';
      form8.ADOQuery2.SQL.Clear;
      form8.ADOQuery2.SQL.Add(Zapros);
      form8.ADOQuery2.Active:=True;
    except
    on e:Exception do
    end;
 //обратно выводим табличку

Zapros:= 'SELECT * FROM '+ IntToStr(Card_num)+' Order by №';
  try
     form8.ADOQuery2.SQL.Clear;
     form8.ADOQuery2.SQL.Add(Zapros);
     form8.ADOQuery2.Active:=True;
  except
    on e:Exception do
    MessageDlg('Не могу подключиться к базе данных!', mtError, [mbOk], 0);
  end;
//теперь задаем смещение и окно
for i:=0 to  records-10 do
begin //1
     sum_X:=0;
     sum_Y:=0;
     sum_Z:=0;
     sum_A:=0;
     for j:=i to (i+9) do  //9 - окно, ровно 10 значений
      begin
        form8.ADOQuery2.Locate('№',j,[loCaseInsensitive]);  //нашел запись по номеру
        sum_X:=sum_X+Form8.ADOQuery2.FieldByName('X').AsFloat; // сложил со старой суммой
        sum_Y:=sum_Y+Form8.ADOQuery2.FieldByName('Y').AsFloat; // сложил со старой суммой
        sum_Z:=sum_Z+Form8.ADOQuery2.FieldByName('Z').AsFloat; // сложил со старой суммой
        sum_A:=sum_A+Form8.ADOQuery2.FieldByName('Общая').AsFloat; // сложил со старой суммой
      end;
       sum_X:=sum_X/10;
       sum_Y:=sum_Y/10;
       sum_Z:=sum_Z/10;
       sum_A:=sum_A/10;
      // вставляем в базу Filter полученные значения
      try
        Zapros:='INSERT INTO Filter (№,X,Y,Z,Общая)VALUES('+IntToStr(i)+','+FloatToStr(sum_X)+','+FloatToStr(sum_Y)+','+FloatToStr(sum_Z)+','+FloatToStr(sum_A)+')';
        form8.ADOQuery3.SQL.Clear;
        form8.ADOQuery3.SQL.Add(Zapros);
        form8.ADOQuery3.ExecSQL;
      except
      end;

end; //1

    try
    Zapros:= 'SELECT * FROM Filter';
      form8.ADOQuery3.SQL.Clear;
      form8.ADOQuery3.SQL.Add(Zapros);
      form8.ADOQuery3.Active:=True;
    except
    on e:Exception do
    end;


Screen.Cursor:=crDefault;
Refresh_table_3(nil);
end;


Спасибо!
PM MAIL   Вверх
CROTishka
Дата 16.11.2010, 09:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 30.7.2009

Репутация: 1
Всего: 2



Мало того, что ваши данные можно получить без всяких временных таблиц одним скулёвым запросом, так ещё и непонятно зачем вы через запросы данные в ADOQuery3 пихаете. Советую переделать добавление так так: http://msdn.microsoft.com/en-us/library/ms677536(VS.85).aspx . Ещё очень много съедает локейт. Используйте TDataSet.Next/Prior + ORDER BY или TCustomADODataSet.Sort. В общем учитесь.

PM MAIL   Вверх
MihailCarib
Дата 16.11.2010, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



О, то, что нужно. Спасибо. Буду познавать. Честно говоря, считал, что локейт быстрее... Только вот не понятно, каким таким хитрым  SQL запросом можно решить сразу всю задачку?

Это сообщение отредактировал(а) MihailCarib - 16.11.2010, 18:17
PM MAIL   Вверх
CROTishka
Дата 16.11.2010, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 30.7.2009

Репутация: 1
Всего: 2



самое банальное, но не очень оптимальное:
Код

SELECT F.№,
       (SELECT SUM (X)
          FROM Filter tmpF
         WHERE tmpF.№ BETWEEN F.№ AND F.№ + 9)
          AS X,
       (SELECT SUM (Y)
          FROM Filter tmpF
         WHERE tmpF.№ BETWEEN F.№ AND F.№ + 9)
          AS Y,
       (SELECT SUM (Z)
          FROM Filter tmpF
         WHERE tmpF.№ BETWEEN F.№ AND F.№ + 9)
          AS Z,
       (SELECT SUM (Общая)
          FROM Filter tmpF
         WHERE tmpF.№ BETWEEN F.№ AND F.№ + 9)
          AS Общая
  FROM Filter F

возможно можно как-то с окнами извратится, или через курсор сделать, чтобы быстрее работало - я привык уже к различным расширениям SQL
PM MAIL   Вверх
MihailCarib
Дата 16.11.2010, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



А, я понял. Сделать запрос на вычисления одного окна -  не проблема. Проблема сдвинуть это окно, ну уж это ладно. Проверил - first/next действительно быстрее Locate, правда не на много, но по копеечке набегает. А запись мне все равно в другую табличку делать, потому как в конце все данные (с обработкой и без) подключаются к DBChart по желанию пользователя, значит их по-любому где-то хранить. Вы мне вот еще что подскажите- буду очень признателен, а нет ли возможности кинуть в DBChart сразу массив данных, не забирая их поэлементно?
Признаюсь, ранее я работал с БД очень мало,  в основном с BDE и задачи такие не ставились, объем информации перелопатить сразу очень большой тяжко, Вы мне хоть направления обозначьте. Спасибо!
PM MAIL   Вверх
superVad
Дата 16.11.2010, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 3
Всего: 15



MihailCarib, ты количество записей вычисляешь до открытия таблицы.
Код

records:= Form8.ADOQuery1.RecordCount;

Не знаю есть ли в этом ошибка (таблица могла быть и до этого открыта), но как то не правильно.
PM MAIL   Вверх
MihailCarib
Дата 16.11.2010, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



Спасибо. Таблица открывается ранее, но ошибка быть могла. Исправлю.
PM MAIL   Вверх
CROTishka
Дата 17.11.2010, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 30.7.2009

Репутация: 1
Всего: 2



Цитата

А запись мне все равно в другую табличку делать, потому как в конце все данные (с обработкой и без) подключаются к DBChart по желанию пользователя, значит их по-любому где-то хранить. 

что мешает вам хранить их в рекордсете/датасете?
Цитата

Вы мне вот еще что подскажите- буду очень признателен, а нет ли возможности кинуть в DBChart сразу массив данных, не забирая их поэлементно?

TChartSeries.AddArray()
PM MAIL   Вверх
MihailCarib
Дата 30.11.2010, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



Все попробовал. Ысе заработало, спасибо! 
Выяснилось, что запрос на добавление записи 
'INSERT INTO '+IntToStr(Card_num) и т.д.

конструкция 

form8.ADOQuery1.Insert;
form8.ADOQuery1.FieldByName('№').AsInteger:=

а также 

form8.ADOQuery1.recordset.AddNew(field,value);

работают примерно одинаково по времени, и для меня неприемлемо медленно. 

Как делаю: есть цикл на чтение данных, данных много, 10000 строк - это норма, инфа читается с флешки. 
В этом цикле после чтения блока данных построчно добавляю информацию в базу, и это не катит по скорости записи. 
Вопрос, как подобные задачи решают нормальные программисты?
Скорость чтения с флешки бешеная, все тормозит именно запись в базу. Куда мне лучше (быстрее) заносить данные во время чтения флешки и как их потом быстро скопом перекидывать в базу?
PM MAIL   Вверх
CROTishka
Дата 1.12.2010, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 30.7.2009

Репутация: 1
Всего: 2



ну добавляйте не построчно, а скопом/блоками, если оперативки хватит в чём проблема?
триггеры на инсерт у вас не стоят?
существенно ускорить процесс поможет только смена БД на нереляционную.
PM MAIL   Вверх
MihailCarib
Дата 1.12.2010, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



Стоп стоп стоп, не так быстро! Я же все-таки чайник, причем кипящий.  Добавлять скопом как? Писать все в массив/файл, а дальше
 ADOQuery1.recordset.AddNew(field,value); 
в value вносить этот массив? Можно примерчик, маленький?
Триггеры на инсерт не стоят, если я правильно понимаю, это счетчики количества записей в самой базе, я их отключил. Но в цикле есть необходимость крутить переменную, я ее использую в качестве поля номера строки. Не очень оптимально,  но я отключал это дело,  совсем копеечки по производительности.
 Вот теперь самое интересное. Программа работала раньше через BDE на таблицах Paradox и все было не сказать что шустро очень, но меня устраивало. Потом оказалось нужно, чтобы все работало без BDE и единственный удачный пример на тот момент я нашел под  Access. 
Access мне использовать удобно, но я был не в курсе таких проблем, как скорость записи/чтения и прочие "мелочи". А теперь эти "мелочи" меня дрючат, но опыта чуток прибавилось, возможно осилю чего другое.
Посоветуйте, с чем сейчас стОит поработать, чтобы пошустрее было? 
PM MAIL   Вверх
CROTishka
Дата 2.12.2010, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 30.7.2009

Репутация: 1
Всего: 2



Для начала научитесь использовать  гугл, прежде чем писать всякую фигню.
Во вторых конечно стоит научиться использовать документацию: http://msdn.microsoft.com/en-us/library/aa...06(SQL.80).aspx
И в третьих, хотя бы отдалённо разобраться в том, как работает то, что вы делаете. (Почитайте хотя бы встроенный хелп - встать на метод, Ctrl+F1)
В четвертых, если хотите помощи, то стоит писать нормально по схеме: "что делаете (ПОДРОБНО), что хотите, что на самом деле получается." 
Иначе помогать никто вам не будет. (У меня сегодня просто ангельское настроение и терпение)

Это сообщение отредактировал(а) CROTishka - 2.12.2010, 10:03
PM MAIL   Вверх
MihailCarib
Дата 2.12.2010, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



Уважаемый CROTishka! Огромное Вам спасибо, за ангельское настроение и терпение! Смею Вас заверить, что в тех областях, в которых я являюсь специалистом, я также, как Вы, на профильных форумах делаю такие приписки, за что меня очень ценят и хотят спрашивать еще и еще. 
Поймите, познать все и сразу невозможно, у меня две вышки, диссер, куча дипломов и пр., но при этом я НЕ УМЕЮ программировать. Пока. Но хочу научиться, не потому, что денег нет,  а потому что интересно. Времени на изучение мне никто не выделяет, все факультативно. Поэтому, не ругайтесь на новичка, пожалуйста. 

За ссылку на MSDN спасибо, про F1 тоже вовремя, но все это я читал, и мои вопросы остались нерешенными. 

Код привести полностью не могу (мне не жалко, просто он большой), процедура такая:
Код

repeat
  SetFilePointer(hdevice,0,nil,FILE_CURRENT);
  ReadFile(hdevice, field, 512, cb, nil); //читает и голову тоже

  for j:=0 to 31 do
                 begin
                 //  присвоение  данных и запись в БД
                  H_r:=(field.srt_w[((j*16)+0)]);       //часы
                  M_t:=(field.srt_w[((j*16)+1)]);        //минуты
                  S_d:=(field.srt_w[((j*16)+2)]);       //секунды
                  D_:=(field.srt_w[((j*16)+3)]);      //день
                  M_:=(field.srt_w[((j*16)+4)]);      // месяц
                  Y_:=(field.srt_w[((j*16)+5)])+2000;     //год
                  X:=coef*ShortInt(field.srt_w[((j*16)+6)]);
                  Y:=coef*ShortInt(field.srt_w[((j*16)+7)]);
                  Z:=coef*ShortInt(field.srt_w[((j*16)+8)]);
               //  T:=(field.srt_w[((a*16)+9)]);  //темп не исп
               //  V:=(field.srt_w[((a*16)+10)]); //скорость не исп
                  a_sum:=SQRT(x*x+y*y+z*z);//суммарная перегрузка

                   begin
                      Date_time_now:= DateTimeToStr(EncodeDateTime(Y_,M_,D_,H_r,M_t,S_d,0));
                        try
                          form8.ADOQuery1.Insert;
                          form8.ADOQuery1.FieldByName('№').AsInteger:=recN_R;
                          form8.ADOQuery1.FieldByName('Дата_Время').AsDateTime:=EncodeDateTime(Y_,M_,D_,H_r,M_t,S_d,0);
                          form8.ADOQuery1.FieldByName('X').AsFloat:=X;
                          form8.ADOQuery1.FieldByName('Y').AsFloat:=Y;
                          form8.ADOQuery1.FieldByName('Z').AsFloat:=Z;
                          form8.ADOQuery1.FieldByName('Общая').AsFloat:=a_sum;
                          form8.ADOQuery1.FieldByName('Оценка').AsInteger:=mark;
                          form8.ADOQuery1.FieldByName('Описание').AsString:=priznak;
                           {    это дб быстрее, но я не заметил
                          value_base:=VarArrayOf([recN_R, EncodeDateTime(Y_,M_,D_,H_r,M_t,S_d,0),X,Y,Z,a_sum,mark,priznak]);
                          form8.ADOQuery1.recordset.AddNew(field_base,value_base); }
                      except
                        on e:Exception do
                      end;
                      inc(recN_R);
                    end;
                 end;

  Progress_pos:=i;
  View_progress(nil);
  Application.ProcessMessages();
  inc(i);
until(i=Sector_count);// крайний сектор  sector_end


В чем проблема: я кручу в цикле обращение к карте ReadFile(hdevice, field, 512, cb, nil); и тут же в цикле открываю таблицу и делаю запись
ADOQuery1.FieldByName('Z').AsFloat:=Z; 
Это не правильно и долго! 
Мне бы хотелось, чтобы в цикле было только обращение к карте и запись , скажем в файл - это будет быстрее, а после цикла в отдельной процедуре вносить данные из файла в базу.  Все примеры, которые мне удалось найти, вносят в базу данные построчно, т.е. так, как это делал я в приведенном коде, либо при помощи ADOQuery1.recordset.AddNew, как описано тут http://msdn.microsoft.com/en-us/library/ms...6(v=VS.85).aspx

Спасибо.


PM MAIL   Вверх
CROTishka
Дата 3.12.2010, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 30.7.2009

Репутация: 1
Всего: 2



Конечно неправильно. Пользоваться активным подключением к бд вообще не правильно. Используйте TADOCommand и изучайте SQL. Ссылку на инсерт я вам дал.
Еще обычно интерфейсную часть тоже показывают.
PM MAIL   Вверх
MihailCarib
Дата 3.12.2010, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.3.2008

Репутация: нет
Всего: нет



Ок, спасибо,буду постигать.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.0612 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.