Текущий архив: 2004.08.08;
Скачать: CL | DM;
ВнизINSERT/UPDATE в одном флаконе Найти похожие ветки
← →
Piter © (2004-07-11 18:41) [0]Есть база с записями. У каждой записи есть уникальное числовое поле, допустим UnicField.
Есть функция, которая добавляет записи в базу, в эту функцию передаются нужные значения полей записей. И функция анализирует, есть ли уже запись с таким значенем поля UnicField в базе или нету. Если есть - она обновляет остальные поля нужной записи (UPDATE), если нету - то добавляет новую запист (INSERT).
Сейчас организовано так - функция делает выборку SELECT COUNT с нужным значением UnicField, и если получится ноль - то добавляет запись, иначе - обновляет существующую. Но дело в том, что все это работает очень медленно. Добавление/обновление 500 записей длится около 7 секунд (Athlon 1800+), При этом чистое добавление записей (без выяснения есть ли запись с таким уникальным UnicField) длится меньше секунды.
Можно как-то сделать такую команду, чтобы запись если существует обновлялась, если не существует - то добавлялась новая запись?
P.S. База - Firebird
← →
Vlad © (2004-07-11 18:54) [1]
> Добавление/обновление 500 записей длится около 7 секунд
> (Athlon 1800+), При этом чистое добавление записей (без
> выяснения есть ли запись с таким уникальным UnicField) длится
> меньше секунды.
Похоже что у тебя запрос на выборку записей неоптимизированный.
Если выборка производится по одному полю, как например:SELECT Count(*) from table where MyUniqueField = SomeValue
то обязательно д.б. индекс по полю MyUniqueField
Если же выборка идет по нескольким полям, напр.SELECT Count(*) from table where MyField1 = SomeValue1 and MyField2 = SomeValue2
В этом случае желательно создать составной индекс MyField1+MyField2
← →
Piter © (2004-07-11 19:02) [2]Vlad (11.07.04 18:54) [1]
спасибо... создал двойной индекс - теперь добавление длится пару секунд... а можно еще быстрее? Чтобы обойтись БЕЗ SELECT?
← →
jack128 © (2004-07-11 19:09) [3]помимо индексов нужно сделать хп в которой и проверять существует ли такая запись
if (exists(select 1 from table where UnicField = :UnicField)) then
begin
update table
set Fie1d1 = :Field1
Field2 = :Field2
..
where
UnicField = :UnicField
end
else
begin
insert into ....
end;
← →
SergP © (2004-07-11 19:26) [4]
> Можно как-то сделать такую команду, чтобы запись если существует
> обновлялась, если не существует - то добавлялась новая запись?
У меня была подобная проблема. Пока я решил ее применением (юзаю ADO) ADOTable вместо ADOQuery, типа так:
with AdoTable do
begin
if seek(Id,soFirstEQ) then edit else insert;
FieldByName("MyField").AsInteger := ....;
...
Post;
end;
Не знаю насколько это хорошо, так как не рекомендуется юзать ADOTable, но правда база у меня локальная, и вроде особых тормозов с этим нет..
Есть еще такой вариант (правда я тоже не уверен в его скорости):
Создаем временную таблицу, куда запихиваем все данные, а затем двумя запросами переносим в основную таблицу сначала те записи с такими значениями уникального поля которые есть в основной таблице (Update)
а затем те, которых нет (INSERT)
← →
Piter © (2004-07-11 20:53) [5]jack128 (11.07.04 19:09) [3]
помимо индексов нужно сделать хп
что такое хп?
← →
jack128 © (2004-07-11 21:17) [6]хранимая процедура. Stored procedure.
← →
Vlad © (2004-07-11 23:17) [7]Впринципе можно и еще быстрее. Достаточно создать уникальный индекс, тогда попытка записи дубля будет приводить к исключению, которое можно соотв. образом обработать на клиенте.
Что-то вроде такого:try
IBSQLInsert.ExecQuery; // Попытка Insert
except
on E: Exception do
begin
// анализ ошибки, если нарушение уникальности, тогда...
IBSQLUpdate.ExecQuery; // Попытка Update
else
raise;
end;
Думаю, что это будет работать быстрее.
← →
jack128 © (2004-07-11 23:28) [8]
> [7] Vlad © (11.07.04 23:17)
нет. Это будет работать медленнее. Значительно медленее. Все проверки нужно делать на сервере в хп. В общем как всегда www.ibase.ru ;-) А конкретно http://www.ibase.ru/devinfo/testiu.htm
← →
Piter © (2004-07-12 00:50) [9]jack128 (11.07.04 23:28) [8]
Дело в том, что база Firebird Embedded - то есть, она локальная. Имеет тогда смысл хп делать?
← →
jack128 © (2004-07-12 01:01) [10]
> Имеет тогда смысл хп делать?
без понятия, не тестил. В любом случае [3] быстрее, чем [0] или [7],вопрос на сколько. Потесть - узнаешь, заодно нам расскажешь ;-)
Но делать "правильно" всегда лудше, чем делать "можно и лудше, но и так сойдет" :-)
← →
Piter © (2004-07-12 17:33) [11]jack128 (12.07.04 01:01) [10]
Блин, все равно ты DMClient используешь...
:)
← →
stone © (2004-07-12 17:55) [12]
> а можно еще быстрее? Чтобы обойтись БЕЗ SELECT?
Использовать две команды в одной транзакции
DELETE FROM ... WHERE UnicField = SomeValue
INSERT INTO ... VALUES ()
PS. Естественно, тут возможны нюансы, но общее направление такое...
Страницы: 1 вся ветка
Текущий архив: 2004.08.08;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.037 c