powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Инкремент
25 сообщений из 35, страница 1 из 2
Инкремент
    #38142754
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения за глупый вопрос, но, что-то я заблудился в трех соснах.

Итак задача: есть набор объектов, по каждому объекту могут возникать события. Пользователь может перевести новое событие в состояние "обработано", а потом в состояние "закрыто". В база порядка сотни объектов. События возникают, ну скажем, раз в полчаса - час по каждому объекту. У каждого объекта может быть сколь угодно закрытых событий и не более 100 новых и обработанных.

Теперь задача - требуется возвратить статус объекта. Пускай будет 0 - есть новые события, 1 - все события обработаны, но есть открытые, 2 - все события закрыты.

Как я это реализовал - добавил в объекты два поля OPEN_CNT, REPORT_CNT. При появлении события вызываю
Код: sql
1.
2.
3.
4.
UPDATE objects SET
  OPEN_CNT = OPEN_CNT + 1
WHERE
  ID = :id

при обработке
Код: sql
1.
2.
3.
4.
5.
UPDATE objects SET
  OPEN_CNT = OPEN_CNT - 1,
  REPORT_CNT = REPORT_CNT + 1
WHERE
  ID = :id

при закрытии
REPORT_CNT = REPORT_CNT - 1
WHERE
ID = :id[/SRC]Потом анализирую значения этих двух счетчиков и выдаю итоговый статус.

Но мучает меня вопрос: а можно ли делать такие апдейты? Не нарвусь ли я в итоге на параллельный апдейт с двух потоков, когда все пойдет в разнос?

Все это происходит на сервере. Т.к. количество объектов число переменное, то использовать генераторы не представляется возможным (или я не вижу как). Добавить статус в само событие а потом делать выборки по этому статусу не хочется, т.к. событий будет накапливаться много

С уважением, Vasilisk
...
Рейтинг: 0 / 0
Инкремент
    #38142776
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_> Но мучает меня вопрос: а можно ли делать такие апдейты?

Можно.

> Не нарвусь ли я в итоге на параллельный апдейт с двух потоков, когда все пойдет в разнос?

Нет. Особенно, если будешь это делать не в RC, а в снапшоте.
Именно инкрментальные апдейты можно и нужно делать в RC,
но если конкуренция невысока, то лично я бы предпочёл
короткий снапшот. Впрочем, если ты имеешь в виду, что
можно нарваться на ошибку (exception) при параллельном
запросе - да, можно, но не вижу с этим проблем, БД и данные
не будут повреждены, просто отлавливай эксепшн.

> Добавить статус в само событие а потом делать выборки по этому
> статусу не хочется, т.к. событий будет накапливаться много

И правильно, это кривая архитектура независимо от количества.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #38143168
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Теперь задача - требуется возвратить статус объекта.

Одного объекта или всех сразу?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #38143366
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамВпрочем, если ты имеешь в виду, что
можно нарваться на ошибку (exception) при параллельном
запросеНет. Имелось в виду. именно целостность данных. Апдейты делаются в коротком RC. Конкуренции практически нет - один поток делает инкремент, второй - декремент.

Спасибо за разъяснения

Dimitry SibiryakovОдного объекта или всех сразу?Всех
...
Рейтинг: 0 / 0
Инкремент
    #38143379
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_> Имелось в виду. именно целостность данных.

Данные не попортятся, но эксепшен теоретически возможен даже при низкой
конкуренции, так что обработку ошибки и повтор операции всё-таки добавь.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #38143407
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Всех
На мой взгляд даже в этом случае для 100 объктов не стоит заморачиваться хранимыми
агрегатами. Индекс на "объект,статус" в таблице событий и запрос
Код: sql
1.
2.
3.
select obj.name,
      (select first 1 status from e where obj=obj.id order by obj,status) status
from obj


вернёт для каждого объекта статус "новый" если есть хоть одно новое событие,
"обработанный" если новых событий нет, но есть незакрытые и "закрыто" во всех остальных
случаях.

Да, это вложенный цикл, но он будет работать всего в 3-4 раза медленнее, поскольку на
каждую запись в таблице объектов будет одно индексное чтение таблицы статусов. Зато нет
тормозов и конкуренции при изменении статусов.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #38143694
Фотография PEAKTOP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_

В целом - оно так и есть. Но можешь в ходе конкуренции потерять статус объекта (станет за счет счетчика, к примеру, 3 или 4)
Приведи задачу к двум регистрам.
1) Регистр остатков - это поля из таблицы объектов (ID, OPEN_CNT, REPORT_CNT). Для красоты и чоткости логики можно создать отдельную VIEW, но это это все уже слишком.
2) Регистр движений - таблица, отражающая движения статуса объектов (ID[OBJECTS], DATE_COMMIT, OPER_CNT, REPORT_CNT), в которую вставляй записи при возникновении события
3) а триггеры регистра движений пусть сами изменяют статус у объекта в регистре остатков. И самое главное - только триггеры могут менять значение в регистре остатков. То есть, нужно что-то поменять - мы добавляем соответствующую запись в регистре движений.

Тогда стопудово получишь картину и историю изменения статуса объектов.
------------
З.Ы. система ограничений - на пространство жесткого диска клиента мы забиваем. условно считаем, что но бесконечно.
...
Рейтинг: 0 / 0
Инкремент
    #38144165
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PEAKTOP> Но можешь в ходе конкуренции потерять статус объекта
PEAKTOP> (станет за счет счетчика, к примеру, 3 или 4)

Ты бредишь.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #38144181
Фотография PEAKTOP
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамТы бредишь.

Да, конечно. Это только результат моего больного воображения. Мне - можно. У меня даже справка есть.

Даю подсказу: одновременно стартуют минимум две (три, десять, ..., n) транзакции
isc_tpb_read_committed
isc_tpb_write
isc_tpb_record_version
isc_tpb_nowait
...
Рейтинг: 0 / 0
Инкремент
    #38144188
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PEAKTOP> Даю подсказу: одновременно стартуют минимум две (три, десять, ..., n) транзакции

Ты развивай мысль, развивай. У тебя уже и подсказка вон есть.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Инкремент
    #39730631
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как правильно увеличить значение поля в хранимой процедуре?

процедура простая, несколько входящих параметров и UPDATE OR INSERT:
Код: sql
1.
UPDATE OR INSERT INTO TABLE1 (USERNAME, FIRSTNAME, LASTNAME, MSG_COUNT) VALUES (USERNAME, :FNAME, :LNAME, MSG_COUNT + 1) MATCHING (USERNAME);



Ошибка возле "MSG_COUNT + 1":
Column unknown MSG_COUNT

Неужели предварительно придётся считывать значение во временную переменную?
...
Рейтинг: 0 / 0
Инкремент
    #39730646
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

двоеточие забыл перед msg_count+1 ? да и перед username тоже. Брось, перепиши в понедельник.
процедуру не вижу.
...
Рейтинг: 0 / 0
Инкремент
    #39730659
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Неужели предварительно придётся считывать значение во временную переменную?

Или так или мозгом подумать: откуда старое значение возьмётся при INSERT.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #39730660
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
09.11.2018 15:15, kdv пишет:
> двоеточие забыл перед msg_count+1 ?

он хочет ПОЛЕ инкрементировать
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Инкремент
    #39730661
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

Боюсь, что если рассуждать логически, то чукча, который инсерт, он же не читатель, а только чисто писатель и у него на момент формирования запроса соответсвующего контекста, с текущими значениями полей просто нема. Потому здесь и VALUE + 1 тоже не прокатит.
...
Рейтинг: 0 / 0
Инкремент
    #39730663
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

используй merge

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
MERGE INTO TABLE1
USING (
  SELECT
    :USERNAME AS USERNAME, 
    :FIRSTNAME AS FIRSTNAME, 
    :LASTNAME AS LASTNAME, 
    COALESCE(:MSG_COUNT, 0) AS MSG_COUNT
) T
ON TABLE1.USERNAME = T.USERNAME
WHEN NOT MATCHED THEN
  INSERT (USERNAME, FIRSTNAME, LASTNAME, MSG_COUNT)
  VALUES (T.USERNAME, T.FIRSTNAME, T.LASTNAME, T.MSG_COUNT)
WHEN MATCHED THEN
  UPDATE SET FIRSTNAME = T.FIRSTNAME,
               LASTNAME = T.LASTNAME,
               MSG_COUNT = MSG_COUNT + 1;
...
Рейтинг: 0 / 0
Инкремент
    #39730666
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

ой, пропустил FROM RDB$DATABASE

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
MERGE INTO TABLE1
USING (
  SELECT
    :USERNAME AS USERNAME, 
    :FIRSTNAME AS FIRSTNAME, 
    :LASTNAME AS LASTNAME, 
    COALESCE(:MSG_COUNT, 0) AS MSG_COUNT
  FROM RDB$DATABASE
) T
ON TABLE1.USERNAME = T.USERNAME
WHEN NOT MATCHED THEN
  INSERT (USERNAME, FIRSTNAME, LASTNAME, MSG_COUNT)
  VALUES (T.USERNAME, T.FIRSTNAME, T.LASTNAME, T.MSG_COUNT)
WHEN MATCHED THEN
  UPDATE SET FIRSTNAME = T.FIRSTNAME,
               LASTNAME = T.LASTNAME,
               MSG_COUNT = MSG_COUNT + 1;
...
Рейтинг: 0 / 0
Инкремент
    #39730671
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Бомба.))
...
Рейтинг: 0 / 0
Инкремент
    #39730677
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,

был бы в Firebird ROW VALUE CONSTRUCTOR этот merge выглядел бы покрасивше и не надо было к RDB$DATABASE обращаться
...
Рейтинг: 0 / 0
Инкремент
    #39730693
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvдвоеточие забыл перед msg_count+1 ? да и перед username тоже.

ок, с параметром username согласен, но MSG_COUNT - это ж не параметр
...
Рейтинг: 0 / 0
Инкремент
    #39730695
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovX11Неужели предварительно придётся считывать значение во временную переменную?

Или так или мозгом подумать: откуда старое значение возьмётся при INSERT.

а если есть default 0?
...
Рейтинг: 0 / 0
Инкремент
    #39730701
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad FX11,

Боюсь, что если рассуждать логически, то чукча, который инсерт, он же не читатель, а только чисто писатель и у него на момент формирования запроса соответсвующего контекста, с текущими значениями полей просто нема. Потому здесь и VALUE + 1 тоже не прокатит.

Было бы здорово, если бы прокатило. При Insert можно было бы вставить NULL либо Default + 1.
...
Рейтинг: 0 / 0
Инкремент
    #39730703
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11а если есть default 0

да по фигу какой там default. Чем тебе merge не катит?
...
Рейтинг: 0 / 0
Инкремент
    #39730717
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я не сказал ,что не катит
просто монстр какой-то получился
а если по производительности - это то же самое, что и предварительный select в переменную, то это даже будет более читабельный код, чем merge
...
Рейтинг: 0 / 0
Инкремент
    #39730740
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

ну про читаемость и монструозность вопрос спорный. Запрос из 10 строчек не такой уж большой, тем более его можно сократить, но в этом случае надо будет одноимённые переменные дважды использовать, что внутри ХП не страшно

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
MERGE INTO TABLE1
USING  RDB$DATABASE
ON TABLE1.USERNAME = :USERNAME
WHEN NOT MATCHED THEN
  INSERT (USERNAME, FIRSTNAME, LASTNAME, MSG_COUNT)
  VALUES (:USERNAME, :FIRSTNAME, :LASTNAME, 0)
WHEN MATCHED THEN
  UPDATE SET FIRSTNAME = :FIRSTNAME,
               LASTNAME = :LASTNAME,
               MSG_COUNT = MSG_COUNT + 1;
...
Рейтинг: 0 / 0
25 сообщений из 35, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Инкремент
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]