Обновлять таблицу MySQL при каждом изменении другой таблицы - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь сократить количество запросов, которые мое приложение использует для построения панели мониторинга, и поэтому я стараюсь собрать всю необходимую мне информацию заранее в одну таблицу. Большая часть панели инструментов может быть встроена в javascript с использованием JSON, что снизит нагрузку на сервер, выполняя тонны PHP foreach, что приводило к избыточным запросам.

Имея это в виду, у меня есть запрос, который собирает информацию о пользователях из 3 других таблиц, объединяет результаты в группе JSON по семейству. Мне нужно обновлять объект JSON каждый раз, когда что-либо меняется в любой из 3 таблиц, но я не уверен, что это «правильный» способ сделать это.

Я мог бы настроить обычную работу для выполнения оператора UPDATE, где дата новее, чем последнее обновление, но при этом пропускаются новые записи, а если я вставляю, пропускаются обновления. Я мог бы удалить и перестроить таблицу, но для выполнения запроса в целом требуется около 16 секунд, так что это не похоже на правильный ответ.

Вот мой начальный запрос:

SET group_concat_max_len = 100000;
SELECT family_id, REPLACE(REPLACE(REPLACE(CONCAT("[", GROUP_CONCAT(family), "]"), "\\", ""), '"[', '['), ']"', ']') as family_members
FROM (

SELECT family_id,
    JSON_OBJECT(
"customer_id",                      c.id, 
"family_id",                        c.family_id,
"first_name",                       first_name,
"last_name",                        last_name,
"balance_0_30",                     pa.balance_0_30,
"balance_31_60",                    pa.balance_31_60,
"balance_61_90",                    pa.balance_61_90,
"balance_over_90",                  pa.balance_over_90,
"account_balance",                  pa.account_balance,
"lifetime_value",                   pa.lifetime_value,
"orders",                           CONCAT("[", past_orders, "]")
) AS family

FROM
    customers AS c
LEFT JOIN accounting AS pa ON c.id = pa.customer_id
LEFT JOIN (
    SELECT patient_id, 
        GROUP_CONCAT(
            JSON_OBJECT(
            "id",                   id,
            "item",                 item,
            "price",                price,
            "date_ordered",         date_ordered
            )
        ) as past_orders 
    FROM orders
    WHERE date_ordered < NOW()
    GROUP BY customer_id
) AS r ON r.customer_id = c.id
where c.user_id = 1

) AS results
GROUP BY family_id

Я кратко рассмотрел триггеры, но то, на что я надеялся, было что-то вроде:

create TRIGGER UPDATE_FROM_ORDERS
AFTER INSERT OR UPDATE
ON orders
(EXECUTE QUERY FROM ABOVE WHERE family_id = orders.family_id)

Я надеялся создать что-то подобное для каждой таблицы, но на первый взгляд не похоже, что вы можете выполнять сложные запросы, такие как тот, где мы создаем вложенный JSON.

Я не прав? Являются ли триггеры правильным способом сделать это, или есть лучший способ?

1 Ответ

0 голосов
/ 27 апреля 2018

В качестве демонстрации:

DELIMITER $$

CREATE TRIGGER orders_au
ON orders
AFTER UPDATE
FOR EACH ROW
BEGIN
   SET group_concat_max_len = 100000
   ;
   UPDATE target_table t
      SET t.somecol = ( SELECT expr 
                          FROM ...
                         WHERE somecol = NEW.family_id
                         ORDER BY ...
                         LIMIT 1
                      )
    WHERE t.family_id = NEW.family_id
   ;
END$$

DELIMITER ;

Примечания:

Триггеры MySQL - это триггеры уровня строки; запускается триггер для «для каждой строки», на который влияет оператор запуска. MySQL не поддерживает триггеры уровня операторов.

Ссылка на NEW.family_id является ссылкой на значение столбца family_id только что обновленной строки, строки, для которой был запущен триггер.

Триггер MySQL запрещает операторам SQL в триггере изменять любые строки в таблице orders. Но это может изменить другие таблицы.

Операторы SQL в теле триггера могут быть произвольно сложными, если только это не чистый SELECT, возвращающий набор результатов, или операторы DML INSERT / UPDATE / DELETE. Операторы DDL (большинство, если не все) запрещены в триггере MySQL.

...