Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Базы данных
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 12.01.2012, 17:23
Rat Rat вне форума
Активный
 
Регистрация: 12.09.2008
Сообщения: 391
Репутация: 6078
По умолчанию Организация очереди для записи в БД

Коллеги, как думаете, как мне лучше реализовать следующее?:

Есть некоторое устройство, с которого по TCPIP каждые 100ms с помощью таймера, считывается значение = 4 байтам. (В дальнейшем предполагается что количество считываемых значений может быть несколько, т.е. должно конфигурироваться).

Ну так вот. Все значения, которые приходят с устройства, необходимо как можно быстрее, записывать в базу данных в одну таблицу, соответственно в таком виде: Id записи, Id переменной, значение, время.

Если сразу писать в базу одно значение, то вроде как всё ОК. всё записывается, всё успевает. Но если несколько, то уже не успевает.

Логично предположить, что необходимо создать некий буфер, который после накопления, будет скидываться в базу данных. Опять же существует вероятность, что при скидывании буфера, данные приходящие в это время, будут потеряны. Поэтому необходимо создать два буфера. Накапливаем один, после накопления, скидываем его в базу, в это время накапливая второй. Ну и всё повторяется заново.
Как думаете, это лучшее решение или есть какие то еще мысли?
Ответить с цитированием
  #2  
Старый 12.01.2012, 18:36
Аватар для Страдалецъ
Страдалецъ Страдалецъ вне форума
Гуру
 
Регистрация: 09.03.2009
Адрес: На курорте, из окна вижу теплое Баренцево море. Бррр.
Сообщения: 4,721
Репутация: 52347
По умолчанию

А какую БД вы используете?
__________________
Жизнь такова какова она есть и больше никакова.
Помогаю за спасибо.
Ответить с цитированием
  #3  
Старый 12.01.2012, 18:42
Аватар для friz
friz friz вне форума
Местный
 
Регистрация: 04.04.2008
Адрес: Минск
Сообщения: 596
Версия Delphi: 2007 & JAVA EE
Репутация: 10670
По умолчанию

Если у вас Oracle то там есть AQ.
Ну если делать все в делфи, то надо делать два потока. первый пишет данные в очередь, второй достает данные из очереди загоняет в бд и удаляет из очереди. В теории как-то все просто, на практике явно будут проблемы
__________________
Последний раз редактировалось Admin, Сегодня в 10:32.
Ответить с цитированием
  #4  
Старый 12.01.2012, 18:53
Аватар для friz
friz friz вне форума
Местный
 
Регистрация: 04.04.2008
Адрес: Минск
Сообщения: 596
Версия Delphi: 2007 & JAVA EE
Репутация: 10670
По умолчанию

ну как-то так :
memo2 - типа входные данные;
memo1 - типа база;

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type

  gggg = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

  TForm1 = class(TForm)
    Timer1: TTimer;
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    Button2: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
procedure gggg.Execute;
begin
  while (form1.Timer1.Enabled) do
    begin
      sleep(205);
      if form1.Memo2.Lines.Count>0 then
                                    begin
                                      form1.Memo1.Lines.add(form1.Memo2.Lines[0]);
                                      form1.Memo2.Lines.Delete(0);
                                    end;
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var g:gggg;
begin
Timer1.Enabled:=true;

g:=gggg.Create(true);
g.Resume;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Enabled:=false;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
memo2.lines.add(inttostr(random(34534534)));
end;

end.
__________________
Последний раз редактировалось Admin, Сегодня в 10:32.
Ответить с цитированием
  #5  
Старый 12.01.2012, 19:23
AlexSku AlexSku вне форума
Специалист
 
Регистрация: 07.05.2007
Адрес: Москва
Сообщения: 884
Репутация: 21699
По умолчанию

Цитата:
Сообщение от Rat
Есть некоторое устройство, с которого по TCPIP каждые 100ms с помощью таймера, считывается значение = 4 байтам. (В дальнейшем предполагается что количество считываемых значений может быть несколько, т.е. должно конфигурироваться).

Ну так вот. Все значения, которые приходят с устройства, необходимо как можно быстрее, записывать в базу данных в одну таблицу, соответственно в таком виде: Id записи, Id переменной, значение, время.

Если сразу писать в базу одно значение, то вроде как всё ОК. всё записывается, всё успевает. Но если несколько, то уже не успевает.
Точно не успевает? По-моему, запись это асинхронная функция (т.е. идёт команда серверу БД, а процессор (программа) может продолжить обработку приёма данных). У нас было общение по CAN-USB линии. После прихода данных шла запись, при этом ещё делался запрос и результат уходил в линию. Компьютер показывал, что на всё уходило 1 мс (правда, другой комп на CAN-шине показывал несколько большее время, но никак не 100 мс).
Ответить с цитированием
  #6  
Старый 12.01.2012, 21:11
Rat Rat вне форума
Активный
 
Регистрация: 12.09.2008
Сообщения: 391
Репутация: 6078
Вопрос

Пока не успевает.
Если делать запись через хранимую процедуру, думаю эффект будет лучше. Особенно если сразу массив передавать.

Но как бы есть вариант что значений будет от 1000 до 100000. Покрайней мере таковы условия заказчика. Хотя лично я думаю, что в реале, больше 5000 не будет. Покрайней мере на одном сервере.

Да. Забыл написать база MSSQL 2008 x64, соответственно крутиться это всё на WIN 2008 R2.

Если честно, мне данная тема интересна.
ИМХО самый быстрый вариант, это запись в бинарные файл конечно. И работа потом с ними. Изучал решения "конкурентов". Хотя мне конечно до них еще далеко.
Сымый лучший вариант это Industiral SQL от Wonderware. Тут есть ConceptGuide, на странице 13 в принципе вся их кухня показана.
Насколько я понимаю, они сделали свой OLEDB провайдер, который средствами SQL позволяет обращаться к бинарным файлам. Один файл - одна переменная. Может как то и по другому конечно оформили. Но принцип один. Все RealTime переменные пишуться в файлы. Далее каким то образом либо кидаются в mdf и становятся так называемыми историческими данными. Но через OLEDB Provider можно обращаться как к Realtime данным, так и к историческим.

У меня правда есть еще один вопрос... как они их упаковывают в такие маленькие объемы. Допустим архив из 5000 значений, за три года, пишется непрерывно каждые 500 милисекунд и занимает 300 мегабайт.. Но это уже следующий этап.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 10:52.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter