Оптимизация внесения данных в БД

  • Автор темы Lunatikus
  • Дата начала
Статус
Закрыто для дальнейших ответов.
L

Lunatikus

#1
БД Access 2002.
Delphi 7.

Вот цикл из проги:
Код:
i:=10;

ADOQ1.open;
ostatok:=ADOQ1.fields[0].asfloat;

ADOQ2.SQL.Clear;
ADOQ2.SQL.append('UPDATE DEAL SET ostatok=:ostatok WHERE univer=:univer AND data=:data');

while i>0 do 
begin
i=i-1;
ADOQ1.next;
ostatok:=ostatok+ADOQ1.fields[1].asfloat+ADOQ1.fields[2].asfloat+ADOQ1.fields[3].asfloat;
ADOQ2.parameters[0].value:=ostatok;
ADOQ2.parameters[1].value:=ADOQ1.fields[4].asstring;
ADOQ2.parameters[2].value:=ADOQ1.fields[5].asdatetime;
ADOQ2.execSQL;
end;
как бы его оптимизировать?а то надо один раз выполнить все это не по 10 строкам а по 500тысячам,а со скоростью 1 строка в 2 секунды это будет очень долго...подскажите,что не так?и как можно оптимизировать?Спасибо за уделенное время!
 
04.09.2006
2 566
3
#2
<!--QuoteBegin-Lunatikus+3:07:2007, 14:41 -->
<span class="vbquote">(Lunatikus @ 3:07:2007, 14:41 )</span><!--QuoteEBegin-->подскажите,что не так?
[snapback]71170" rel="nofollow" target="_blank[/snapback]​
[/quote]
Такие запросы нужно делать на стороне сервера, т.е. необходимо написать один (!!!) запрос, обновляющий все записи. Эти ваши постоянные выборки-вставки отрицательно сказываются на быстродействии. А про 500 тыщ это серьезно? При таких объемах уже давно пора отказаться от Access
 
L

Lunatikus

#3
тогда вопрос-что позволит в mySQL сделать это быстрее?И каким образом сделать один запрос?У меня ADOQ1 итак двойной left joinовый по трем таблицам.Я даже не представляю как результаты его совместить с updateом...ну новичок я,новичок...потому и прошу совета.В принципе,я собираюсь делать в итоге на mySQL,но пока не имею возможности и приходиться костяк проги делать с accessom.
 
04.09.2006
2 566
3
#4
Покажи структуру своих таблиц и расскажи что надо сделать. Может помогу...
 
L

Lunatikus

#5
DEAL:
data PK
univer PK
ostatok
prognoz

V_PUTI:
fil PK
univer PK
kolc
data PK

ZAK:
n_zak PK
org
univer
razmer
data_zak
manager
active
data_sozd

А сделать надо следующее:
Я получаю такой набор данных:

DEAL_VIRTUAL:
data (DEAL)
univer(DEAL)
ostatok
prognoz(DEAL)
kolc (V_PUTI)(суммируются все kolc(V_PUTI) по univer и data и совмещается с DEAL по полям univer и data)
razmer (ZAK)(суммируются все razmer(ZAK) по univer и data и совмещается с DEAL по полям univer и data)
C ним я делаю уже расчеты значения поля ostatok:
поле ostatok ,берется из DEAL(оно имеет значения только на текущую дату data,после чего расчитываются следующие строки как указано в коде:eek:statok(next)=ostatok+kolc-prognoz-razmer)
после вычислений,результат надо занести в DEAL,чтобы получить заполненную таблицу значениями ostatok.
Т.е. все,ради чего я это делал-чтобы заполнить поле ostatok(DEAL) на основе данных из ZAK,V_PUTI.
 
L

Lunatikus

#6
Перешел на MS SQL server 2000.Скорость возросла в дцать раз.Топик можно закрыть.

Спасибо,European,твое замечание по аксесу стало последней каплей,теперь работаю с более вменяемой для таких наборов данных базой.Было бы,конечно,лучше еще быстрее сделать,все равно довольно медленно.В любом случае данная операция будет делаться единожды-для создания базы для последующих изменений.
 
04.09.2006
2 566
3
#7
Для: Lunatikus
Ой, забыл про твой запрос... Сейчас попробую написать
 
04.09.2006
2 566
3
#8
У-ф-фф... Запарился:( Последовательность написания запроса такова:

1. Сделаем запрос на получение полей kolc и razmer
Код:
SELECT v.data as data, v.univer as univer, sum(v.kolc) as kolc, sum(z.razmer) as razmer
FROM Deal d
LEFT FOIN V_Puti v ON d.data = v.data AND d.univer = v.univer
LEFT JOIN Zak z ON d.data = z.data_zak AND d.univer = z.univer
GROUP BY v.kolc, z.razmer
2. Вычислим значение поля ostatok
Код:
SELECT d.data as data, d.univer as univer, (d.ostatok + dv.kolc – dv.razmer) as ostatok 
FROM Deal d LEFT JOIN
(
SELECT v.data as data, v.univer as univer, sum(v.kolc) as kolc, sum(z.razmer) as razmer
FROM Deal d
LEFT FOIN V_Puti v ON d.data = v.data AND d.univer = v.univer
LEFT JOIN Zak z ON d.data = z.data_zak AND d.univer = z.univer
GROUP BY v.kolc, z.razmer
) Deal_Virtual dv ON ON d.data = dv.data AND d.univer = dv.univer
3. Напишем результирующий запрос на обновление
Код:
UPDATE Deal SET ostatok = 
(
SELECT Data.ostatok
FROM Deal LEFT JOIN
(
SELECT d.data as data, d.univer as univer, (d.ostatok + dv.kolc – dv.razmer) as ostatok 
FROM Deal d LEFT JOIN
(
SELECT v.data as data, v.univer as univer, sum(v.kolc) as kolc, sum(z.razmer) as razmer
FROM Deal d
LEFT FOIN V_Puti v ON d.data = v.data AND d.univer = v.univer
LEFT JOIN Zak z ON d.data = z.data_zak AND d.univer = z.univer
GROUP BY v.kolc, z.razmer
) Deal_Virtual dv ON ON d.data = dv.data AND d.univer = dv.univer
) UpdatedValues
ON Deal.data = UpdatedValues.data AND Deal.univer = UpdatedValues.univer
)
Ты не привел правила для расчета поля prognoz поэтому я его не учитывал. Также неочевидно по какой дате идет связь с таблицей Zak, поэтому я использовал data_zak. Скорее всего с первого раза не заработает, так что спрашивай если что. Советую отлаживать по пунктам
 
L

Lunatikus

#9
Я доделывал свой вариант,потому так долго не отвечал.Потом попробовал твой враиант-ушло правда время чтобы его подправить-ошибки были.В итоге получилось практически одно быстродействие-мой вариант все с теми же двумя запросами-работа с одним и периодическая запись данных с помощью другого.К тому же у меня планируется добавление еще нескольких операций записи-а это значит еще большее усложнение в твоем варианте-в моем же просто добавлю отдельный простенький запрос.Ты,конечно же,прав,что надо использовать единый запрос,но для меня в данный момент это нецелесообразно.Спасибо за уделенное время и помощь!
 
Статус
Закрыто для дальнейших ответов.