|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Нужна помощь в связке 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
|
|||
|
|||
1. Использовать транзакцию. Т.е. все действия делать в одной транзакции.
2. Сначала получить выборку по ключевым полям на клиента и проверять в памяти (не надо делать доп. запрос на каждую запись). Конечно, если такая выборка не очень большая. 3. Переложить проверку на сервер, создав уникальный констрейнт по ключевым полям. Тогда вообше проверять не надо - в случае, если запись с такими значениями существует, то просто будет ошибка вставки. 4. Batch insert - объединить несколько операций в ставки в один запрос (кстати, как раз MySQL кажется поддерживает для этого специальный формат запроса INSERT). |
#3
|
|||
|
|||
1. Видимо не получится без хитрого запроса, который и проверяет, и обновляет, и вставляет
2. Вариант. Т.е. сначала все записи селектом считываю, и с fields запроса работаю, Вы это ввиду имеете? 3. Про это вообще не понял. Поищу в инете что такое констрейнт 4. Думал про это, но не очень удобно опять же из-за проверок и в один запрос собрать вставку очень большого числа записей наверное не очень правильно. В любом случае спасибо. Есть ещё идеи? Конечно не откажусь и от куска кода) |
#4
|
||||
|
||||
в Firebird есть оч удобная команда:
Код:
UPDATE OR INSERT INTO <таблица>(<список полей>) VALUES(<список значений>) MATCHING (<поля по которому ищется совпадение>) Поживу - увижу, Доживу - узнаю, Выживу - учту. [P.S.]->Выражая благодарность за помощь - Вы получаете шанс на помощь в следующий раз
|
#5
|
|||
|
|||
Да, нашёл нечто похожее:
Цитата:
Единственное, что непонятно- если в таблице несколько индексов, то как натравить запрос на проверку совпадений только по определённым индексам? |
#6
|
|||
|
|||
Есть ещё у кого- нибудь мысли по этому поводу? Очень нужна помощь. Расписывать ничего не надо, подтолкните чисто)
|