Страница 1 из 3
Промежуточный commit
Добавлено: 12 дек 2006, 13:15
Kyarginski
Добрый день!
Подскажите, добрые люди!
Есть хранимая процедура:
Код: Выделить всё
CREATE PROCEDURE My_Proc
as
declare P_MY_FLD varchar(20);
begin
FOR
SELECT MY_FLD
FROM MY_TAB
INTO :P_MY_FLD
DO
BEGIN
execute procedure MY_OTHER_Proc(:P_MY_FLD);
[b]COMMIT;[/b]
END
end
Могу ли я поставить
COMMIT в указанном месте?
Компилятор не позволяет...
Хочется подтверждать каждое действие...
Подскажите решение!!!
Версия сервера FireBird 2.0
Re: Промежуточный commit
Добавлено: 12 дек 2006, 13:20
adima
Kyarginski писал(а):Могу ли я поставить
COMMIT в указанном месте?
Компилятор не позволяет...
Хочется подтверждать каждое действие...
Подскажите решение!!!
Версия сервера FireBird 2.0
транзакциями управляет клиентское приложение, в хранимой процедуре на сервере это невозможно
Добавлено: 12 дек 2006, 13:24
Kyarginski
Спасибо за оперативный ответ!
транзакциями управляет клиентское приложение, в хранимой процедуре на сервере это невозможно
Печально...
Совсем совсем ничего нельзя сделать?
Дергать с клиента эту процедуру?
Добавлено: 12 дек 2006, 14:41
kdv
Совсем совсем ничего нельзя сделать?
видишь-ли, процедура относится к операторам SQL, поэтому как таковая она и так атомарна. Вызов commit/rollback на сервере это неправильная идея.
Дергать с клиента эту процедуру?
а как ее еще можно вызвать???
Добавлено: 12 дек 2006, 14:47
Kyarginski
а как ее еще можно вызвать???
Ну...
По аналогии с, например, Oracle , хочется вызвать внутри SQL-блока и подтверждать изменения через тысячу записей...
Oracle
commit воспринимает более благосклонно.

Добавлено: 12 дек 2006, 14:51
WildSery
Kyarginski писал(а):хочется вызвать внутри SQL-блока и подтверждать изменения через тысячу записей...
Для каждой задачи есть несколько вариантов решения. Не упирайся в одну-единственную найденную и показавшуюся удобной возможность.
И в оракуле с такой постановкой задачи с консерваторией в первую очередь разбираться надо.
Добавлено: 12 дек 2006, 15:06
Kyarginski
ОК.
Спсиба
Думать буду!
P.S. А какие ещё возможности в данном случае существуют?
Тогда опишу изначальную задачу...
Может быть подскажите оптимальный вариант решения для FireBird.
Есть БД ~ 4 млн. записей.
Необходимо:
- - сгруппировать записи по определенному полю
- оставить в БД запись с максимальной датой (остальные удалить)
решение "в лоб" написанием селекта с group by по полю и одновременным удалением - работает безбожно долго (да конца не дождался...)
Что посоветуете?
Добавлено: 12 дек 2006, 16:50
Kyarginski
Мда...
Идей никаких?
Добавлено: 12 дек 2006, 17:02
WildSery
Код: Выделить всё
delete from Table1
where aDate not in (select max(aDate) from Table1 group by GroupField)
Единственно, что неясно - какое отношение эта задача имеет к первоначальному вопросу?
Добавлено: 12 дек 2006, 17:25
Kyarginski
Единственно, что неясно - какое отношение эта задача имеет к первоначальному вопросу?
Самое прямое...
Подобный запрос не дорабатывал до конца (работал почти сутки)
Захотелось выполнить задачу по частям!
Для этого и понадобился промежуточный COMMIT.
delete from Table1
where aDate not in (select max(aDate) from Table1 group by GroupField)
Кстати, тоже не корректный запрос!
Он же удалит все данные кроме максимальной aDate, не взирая на GroupField?!
Надо примерно следующее
delete FROM Table1 T1 WHERE
EXISTS
(SELECT 1 FROM Table1 T2 WHERE
(T2.GroupField = T1.GroupField) AND
(T2.aDate < (SELECT max(aDATE) FROM Table1 T3 WHERE
(T2.GroupField = T3.GroupField)
)))
Во как!

Добавлено: 12 дек 2006, 18:43
Merlin
На мой взгляд, запрос без связки по ID несколько рискованный. И не самый быстрый. Я бы не морщил моск и вынес бы группировку во внешний цикл, хоть в SP хоть на клиенте, а удалял бы внутри по ID. Когда речь идёт об умирании запросов на каких-то 4-х лимонах, то это однозначно говорит о хреновых планах на хреновых индексах. Не обязательно хреновых по жизни, а хреновых для этого запроса. Типа
COUNT
===========
4030740
Код: Выделить всё
select count (distinct code)
from sebgup_arc
COUNT
===========
2118
а теперь группировка с полным фетчем:
Код: Выделить всё
select count(*), code
from sebgup_arc
group by code
PLAN (SEBGUP_ARC ORDER SEBGUPA_SPR)
Elapsed time= 568.33 sec
Код: Выделить всё
select count(*), code+0
from sebgup_arc
group by 2
PLAN (SEBGUP_ARC NATURAL)
Elapsed time= 16.01 sec
Этому компу уже года 4. Если нужно отфетчить весь результат сортировки/группировки, то натурал выиграет всегда и тем больше, чем больше её объём. А вот если надо быстро отфетчить первый десяток строк, а дальше трава не расти - то обычно (когда индекс не по полю да/нет) наоборот.
Добавлено: 12 дек 2006, 18:48
WildSery
Да, это я чего-то заработался. Запрос построил не для даты, а для ID.
В том смысле, что оно уникально.
Вообще, если это штатная команда, я бы в процедуру забил, и вызывал процедуру.
Код: Выделить всё
create procedure KillAllExceptMaxDate
as
declare variable aDate timestamp;
declare variable GroupField <type>;
begin
for select max(aDate), GroupField
from Table1
group by GroupField
into aDate, GroupField
do
delete from Table1
where GroupField = :GroupField and aDate < :aDate;
end;
Добавлено: 13 дек 2006, 09:38
Kyarginski
O!
Спасибо за советы!
Сначала попробовал процедуру по аналогии с
KillAllExceptMaxDate.
6 часов - никаких результатов...
Или ещё ждать?
И сколько?
Может быть попробовать сделать
select max(aDate), GroupField||''
from Table1
group by GroupField
into aDate, GroupField
?
Как Вы думаете, поможет?
P.S. Небольшие уточнение
- Таблица БОЛЬШАЯ;
- из таблицы будут проводиться только SELECT'ы;
- добавления очень-очень редко (или никогда);
- созданы индексы по ВСЕМ полям (для сортировки на клиенте по выбранному полю в гриде);
Индексы могут мешать выборке?
"Плохие" индексы и т.п. ?
Добавлено: 13 дек 2006, 09:49
Dimitry Sibiryakov
Kyarginski писал(а): - созданы индексы по ВСЕМ полям (для сортировки на клиенте по выбранному полю в гриде);
Индексы могут мешать выборке?
"Плохие" индексы и т.п. ?
Да ты, я смотрю, с Парадокса рухнул. Лишние индексы могут помешать всему (и в твоем случае - мешают). Самое смешное, что для "сортировки на клиенте" они тоже совсем не нужны.
Дропни все индексы какие сможешь и повтори операцию. Удаление должно пройти максимум за пару минут.
Добавлено: 13 дек 2006, 10:51
WildSery
[quote="Kyarginski"][/quote]Иногда индекс может и помочь.
Но не в случае, когда ты делаешь запрос по всем данным таблицы.
Покажи статистику по индексу по полю группировки.
Добавлено: 13 дек 2006, 10:57
Kyarginski
Покажи статистику по индексу по полю группировки.
Глупый вопрос:
А как это сделать?
Добавлено: 13 дек 2006, 11:04
Kyarginski
В IBExpert'e в таблице напротив индекса с полем, по которому идёт группировка в колонке Статистика стоит число 0.00000016647.
Как ещё статистику посмотреть?
Добавлено: 13 дек 2006, 11:13
WildSery
Kyarginski писал(а):В IBExpert'e в таблице напротив индекса с полем, по которому идёт группировка в колонке Статистика стоит число 0.00000016647.
Там ещё можно ткнуть "пересчитать статистику".
Что ж ты говоришь, что у тебя около 4 млн. записей, если у тебя только по _группировочному_ полю 6 млн. уникальных значений?
Добавлено: 13 дек 2006, 11:17
Kyarginski
Сорри...
Это я про тестовую БД говорил... 4 млн.
А на рабочей все 15 будет
P.S. На тестовой тоже долго удаляет
Добавлено: 13 дек 2006, 12:54
Dimitry Sibiryakov
WildSery писал(а):Покажи статистику по индексу по полю группировки.
Да этот-то индекс скорее всего ерунда, а вот представь как напрягается сервер перестраивая хотя бы десяток индексов (или сколько там у него полей). Да еще я не удивлюсь, если автор создал еще по индексу в дубль к PK и FK.