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

Delphi Sources



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

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 23.11.2012, 02:33
rumsc rumsc вне форума
Прохожий
 
Регистрация: 23.11.2012
Сообщения: 4
Репутация: 10
По умолчанию Нужна помощь в связке delpi+mysql

Итак, сабж.
Для работы с мускулом использую DAC.
Проблема такая - импортирую данные из stringgrid в БД.
В таблице 40 тыс. записей, всё это дело импортируется около 40 минут. Интересует возможность ускорить процесс.
Что делаю:
1) Читаю строку из экселя
2) Проверяю есть ли такая в БД ( по двум параметрам)
3) Если есть- обновляю
4) Если нет - добавляю данные в таблицу товаров, определяю id добавленного элемента, по нему добавляю запись в таблицу поставщиков

Код:
Код:
var n,m:integer;
    pars:boolean;
    m_id:integer;
    time1,time2:TTime;
    max_id:integer;
begin
Time1:=now;
pars:=true;
{mysqlquery1.Close;
mysqlquery1.SQL.Clear;
mysqlquery1.SQL.Add('LOCK TABLES tovary WRITE, postavschiki WRITE');
mysqlquery1.ExecSQL; }
            mysqlquery1.Close;
            mysqlquery1.SQL.Clear;
            mysqlquery1.SQL.Add('SELECT MAX(id) from tovary');
            mysqlquery1.Open;
            if mysqlquery1.RecordCount<>0 then m_id:=mysqlquery1.Fields.Fields[0].AsInteger else m_id:=0;
             inc(m_id);

for n:=1 to StringGrid1.RowCount-1 do
  begin
    pars:=true;
        mysqlquery1.Close;
        mysqlquery1.SQL.Clear;
    if (StringGrid1.Cells[ComBoBox1.Items.indexof(ComboBox1.Text),n]='') or
       (StringGrid1.Cells[ComBoBox2.Items.indexof(ComboBox2.Text),n]='') or
       ((ComBoBox3.Text='') and (CheckBox1.Checked=false))or
       (StringGrid1.Cells[ComBoBox4.Items.indexof(ComboBox4.Text),n]='') or
       (StringGrid1.Cells[ComBoBox5.Items.indexof(ComboBox5.Text),n]='') or
       (StringGrid1.Cells[ComBoBox6.Items.indexof(ComboBox6.Text),n]='') then pars:=false;

    if pars<>false then
    begin
        // Ïðîâåðêà íà ñóùåñòâîâàíèå èìïîðòèðóåìîé çàï÷àñòè
{        mysqlquery4.Close;
        mysqlquery4.SQL.Clear;}

        mysqlquery1.SQL.Add('select t1.id as id,t1.inv_num, t2.name,t2.zapchastPrice as zprice,t2.ostatok as zost from tovary as t1, postavschiki as t2 where t1.inv_num=:inv_num and t2.izgotname=:izgotname and t2.zapchastid=t1.id');
        mysqlquery1.ParamByName('inv_num').AsString:=StringGrid1.Cells[ComBoBox2.Items.indexof(ComboBox2.Text),n];
        mysqlquery1.ParamByName('izgotname').AsString:=StringGrid1.Cells[ComBoBox4.Items.indexof(ComboBox4.Text),n];
        mysqlquery1.Open;

        if mysqlquery1.RecordCount=0 then
          begin
            mysqlquery1.Close;
            mysqlquery1.SQL.Clear;
            mysqlquery1.SQL.Add('insert into tovary (id,inv_num,name,kross_num) values (:id,:inv_num,:name,:kross_num)');
            mysqlquery1.ParamByName('inv_num').AsString:=StringGrid1.Cells[ComBoBox2.Items.indexof(ComboBox2.Text),n];
            mysqlquery1.ParamByName('name').AsString:=StringGrid1.Cells[ComBoBox1.Items.indexof(ComboBox1.Text),n];
            mysqlquery1.ParamByName('id').AsInteger:=m_id;
            if checkbox1.Checked then mysqlquery1.ParamByName('kross_num').AsString:='0' else
              mysqlquery1.ParamByName('kross_num').AsString:=StringGrid1.Cells[ComBoBox3.Items.indexof(ComboBox3.Text),n];
            mysqlquery1.ExecSQL;

            mysqlquery1.Close;
            mysqlquery1.SQL.Clear;
            mysqlquery1.SQL.Add('insert into postavschiki (name,zapchastID,zapchastPrice,izgotName,ostatok) values (:name,:zapchastID,:zapchastPrice,:izgotName,:ostatok) ');
            mysqlquery1.ParamByName('name').AsString:=Edit1.Text;                                        s
            mysqlquery1.ParamByName('zapchastID').AsInteger:=m_id;
            mysqlquery1.ParamByName('zapchastPrice').AsFloat:=StrToFloat(StringGrid1.Cells[ComBoBox5.Items.indexof(ComboBox5.Text),n]);
            mysqlquery1.ParamByName('izgotName').AsString:=StringGrid1.Cells[ComBoBox4.Items.indexof(ComboBox4.Text),n];
            mysqlquery1.ParamByName('ostatok').AsInteger:=StrToInt(StringGrid1.Cells[ComBoBox6.Items.indexof(ComboBox6.Text),n]);
            mysqlquery1.ExecSQL;
            inc(m_id);
        end
        else
        begin
          max_id:=mysqlquery1.Fields.Fields[0].AsInteger;
          mysqlquery1.Close;
          mysqlquery1.SQL.Clear;
          mysqlquery1.SQL.Add('update postavschiki set zapchastprice=:zapchastprice, ostatok=:ostatok where zapchastID=:id');
          mysqlquery1.ParamByName('zapchastprice').AsFloat:=StrToFloat(StringGrid1.Cells[ComBoBox5.Items.indexof(ComboBox5.Text),n]);
          mysqlquery1.ParamByName('ostatok').AsInteger:=StrToInt(StringGrid1.Cells[ComBoBox6.Items.indexof(ComboBox6.Text),n]);
          mysqlquery1.ParamByName('id').AsInteger:=max_id;
          mysqlquery1.ExecSQL;
        end;
  end;
  end;
{mysqlquery1.Close;
mysqlquery1.SQL.Clear;
mysqlquery1.SQL.Add('UNLOCK TABLES');
mysqlquery1.ExecSQL; }
time2:=now;
    ShowMessage('import is done'+#13+'Âðåìÿ íà÷àëà: '+TimeToStr(time1)+#13+'Âðåìÿ îêîí÷àíèÿ: '+TimeToStr(time2));
    Form2.Close;

Структура таблиц:
1) tovary (
id int(11) Нет Нет AUTO_INCREMENT
inv_num varchar(30) cp1251_general_ci Нет Нет
catID varchar(30) cp1251_general_ci Нет Нет
name varchar(30) cp1251_general_ci Нет Нет
kross_num varchar(30) cp1251_general_ci Нет Нет
price_prodaja)

2) postavschiki (
id int(11) Нет Нет AUTO_INCREMENT
name varchar(30) cp1251_general_ci Да NULL
contacts varchar(50) cp1251_general_ci Да NULL
zapchastID int(11) Нет Нет
zapchastPrice float Нет Нет
izgotName varchar(30) cp1251_general_ci Да NULL
ostatok
)

В mysql не силён, прошу помощи как всё это дело можно "облегчить". Есть конечно идеи, хотелось бы узнать мнение специалистов. Спасибо!
Ответить с цитированием
  #2  
Старый 23.11.2012, 06:09
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,035
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

1. Использовать транзакцию. Т.е. все действия делать в одной транзакции.
2. Сначала получить выборку по ключевым полям на клиента и проверять в памяти (не надо делать доп. запрос на каждую запись). Конечно, если такая выборка не очень большая.
3. Переложить проверку на сервер, создав уникальный констрейнт по ключевым полям. Тогда вообше проверять не надо - в случае, если запись с такими значениями существует, то просто будет ошибка вставки.
4. Batch insert - объединить несколько операций в ставки в один запрос (кстати, как раз MySQL кажется поддерживает для этого специальный формат запроса INSERT).
Ответить с цитированием
  #3  
Старый 23.11.2012, 11:12
rumsc rumsc вне форума
Прохожий
 
Регистрация: 23.11.2012
Сообщения: 4
Репутация: 10
По умолчанию

1. Видимо не получится без хитрого запроса, который и проверяет, и обновляет, и вставляет
2. Вариант. Т.е. сначала все записи селектом считываю, и с fields запроса работаю, Вы это ввиду имеете?
3. Про это вообще не понял. Поищу в инете что такое констрейнт
4. Думал про это, но не очень удобно опять же из-за проверок и в один запрос собрать вставку очень большого числа записей наверное не очень правильно.
В любом случае спасибо. Есть ещё идеи? Конечно не откажусь и от куска кода)
Ответить с цитированием
  #4  
Старый 23.11.2012, 12:45
Аватар для Yurk@
Yurk@ Yurk@ вне форума
Специалист
 
Регистрация: 07.09.2007
Адрес: Украина, г. Днепропетровск
Сообщения: 892
Версия Delphi: 7 + ОгнеПтица
Репутация: выкл
По умолчанию

в Firebird есть оч удобная команда:
Код:
UPDATE OR INSERT INTO <таблица>(<список полей>)
VALUES(<список значений>)
MATCHING (<поля по которому ищется совпадение>)
думаю и в мускуле должно быть что-то аналогичное
__________________
Поживу - увижу, Доживу - узнаю, Выживу - учту.
[P.S.]->Выражая благодарность за помощь - Вы получаете шанс на помощь в следующий раз
Ответить с цитированием
  #5  
Старый 23.11.2012, 13:12
rumsc rumsc вне форума
Прохожий
 
Регистрация: 23.11.2012
Сообщения: 4
Репутация: 10
По умолчанию

Да, нашёл нечто похожее:
Цитата:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]

Единственное, что непонятно- если в таблице несколько индексов, то как натравить запрос на проверку совпадений только по определённым индексам?
Ответить с цитированием
  #6  
Старый 23.11.2012, 20:45
rumsc rumsc вне форума
Прохожий
 
Регистрация: 23.11.2012
Сообщения: 4
Репутация: 10
По умолчанию

Есть ещё у кого- нибудь мысли по этому поводу? Очень нужна помощь. Расписывать ничего не надо, подтолкните чисто)
Ответить с цитированием
Ответ


Delphi Sources

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

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

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

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


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


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

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

ВКонтакте   Facebook   Twitter