Найдено результатов: 1

Как поддерживать рекурсивный инвариант в базе данных MySQL?

У меня есть дерево, закодированное в базе данных MySQL как ребра:

CREATE TABLE items (
    num INT,
    tot INT,
    PRIMARY KEY (num)
    );
CREATE TABLE tree (
    orig INT,
    term INT
    FOREIGN KEY (orig,term) REFERENCES items (num,num)
    )

Для каждого листа в дереве, items.tot устанавливается кем-то. Для внутренних узлов items.tot должен быть суммой его дочерних элементов. Повторное выполнение следующего запроса приведет к желаемому результату.

UPDATE items SET tot = (
    SELECT SUM(b.tot) FROM
        tree JOIN items AS b
        ON tree.term = b.num 
        WHERE tree.orig=items.num)
    WHERE EXISTS 
        (SELECT * FROM tree WHERE orig=items.num)

(обратите внимание, что это на самом деле не работает, но это к делу не относится)

Предположим, что база данных существует и инвариант уже удовлетворен.

Вопрос в том:

Каков наиболее практичный способ обновления DB при сохранении этого требования? Обновления могут перемещать узлы вокруг или изменять значение tot на конечных узлах. Можно предположить, что листовые узлы останутся листовыми узлами, внутренние узлы останутся внутренними узлами, и все это останется как правильное дерево.

Некоторые мысли у меня были:

  • Полное аннулирование, после любого обновления, пересчитать все (ум... Нет)
  • Установите триггер в таблице элементы для обновления родительского элемента любой обновляемой строки
    • Это было бы рекурсивно (обновления запускают обновления, запускают обновления,...)
    • Не работает, MySQL не может обновить таблицу, которая запустила триггер
  • Установите триггер для планирования обновления родительского элемента любой обновляемой строки
    • Это было бы итеративно (получить элемент из расписания, обработка его планирует больше элементов)
    • Что же это такое? Доверяйте клиентскому коду, чтобы получить его правильно?
    • Преимущество заключается в том, что если обновления упорядочены правильно, то меньше сумм должно быть вычислено. Но этот порядок сам по себе является осложнением.

Идеальное решение было бы обобщить на другие "aggregating invariants"

FWIW я знаю, что это "немного за бортом", но я делаю это для удовольствия (Fun: verb, находя невозможное, делая это. :-)

mysql   algorithm   data-structures   invariants    

448   2   12:03, 15th August, 2020