powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Поговорим о триггерах
12 сообщений из 12, страница 1 из 1
Поговорим о триггерах
    #40030345
Prizzrak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть у меня одна задача. Ускорить одну хорошую CMS. Ну не всю конечно, а те места где я выбираю данные для вывода на страницы сайта. Проблема в том, что структура базы данных CMS такова, что все значения всех полей объектов хранятся в отдельной таблице и связаны с таблицей объектов с помощью внешнего ключа. В итоге чтобы скажем провести фильтрацию данных по 3-м полям там городится запрос с джойнами двух таблиц самих на себя. Если данных не много это отрабатывает относительно быстро, но если их много, это всё тормозит. Страница сайта формируется 2 секунды. Казалось бы не много, но по современным меркам если формирование более 0,5 секунды - это уже долго.

Поскольку структуру БД этой CMS я менять не могу, точнее не могу менять таблицы, которые идут с самой CMS, то у меня возникла идея добавить в базу свои таблицы, в которых развернуть эти объекты в плоский вид. Тоесть чтобы в одной строке таблицы были все нужные поля и отобрав из этой таблицы нужные объекты в основной таблице отбирать объекты уже не по полям, а по ID. В этом случае количество джойнов сократится существенно и всё будет работать быстро.

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

Как считаете, стоит так делать? Я слышал, что триггеры не рекомендуют лишний раз использовать. Это может привести к проблемам. Может у кого опыт были? Есть ли смысл заморачиваться с триггерами или может лучше сразу всё это перенести на уровень php?
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030352
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Prizzrak
структура базы данных CMS такова, что все значения всех полей объектов хранятся в отдельной таблице и связаны с таблицей объектов с помощью внешнего ключа.
Надо понимать речь идёт об обычной EAV-схеме.

Prizzrak
чтобы скажем провести фильтрацию данных по 3-м полям там городится запрос с джойнами двух таблиц самих на себя.
Для этого используется условная агрегация. Никакие джойны не требуются. См. "реляционное деление".

Prizzrak
у меня возникла идея добавить в базу свои таблицы, в которых развернуть эти объекты в плоский вид.
Переопределённые данные - почти всегда плохое решение.

Prizzrak
Есть ли смысл заморачиваться с триггерами
Нет.

Prizzrak
или может лучше сразу всё это перенести на уровень php?
Тем более нет.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030682
Prizzrak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот запрос который генерируется CMS на одном из блоков страницы:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
SELECT DISTINCT SQL_CALC_FOUND_ROWS
    h.id AS id, h.rel AS pid
FROM
    cms3_hierarchy h,
    cms3_permissions p,
    cms3_objects o
        LEFT JOIN
    cms3_object_content oc_509_lj ON oc_509_lj.obj_id = o.id
        AND oc_509_lj.field_id = '509'
        LEFT JOIN
    cms3_object_content oc_516_lj ON oc_516_lj.obj_id = o.id
        AND oc_516_lj.field_id = '516'
        LEFT JOIN
    cms3_object_content oc_517_lj ON oc_517_lj.obj_id = o.id
        AND oc_517_lj.field_id = '517'
WHERE
    h.type_id IN (56)
        AND ((oc_509_lj.int_val = '1'
        OR oc_516_lj.int_val = '1'
        OR oc_517_lj.int_val = '1'))
        AND h.lang_id = '1'
        AND h.is_deleted = '0'
        AND h.is_active = '1'
        AND (p.rel_id = h.id AND p.level & 1
        AND p.owner_id IN (579))
        AND h.id IN (33 , 28, 24, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 104,  22,  121,  61,  37, 34, 58, 35, 41, 56)
        AND h.obj_id = o.id
ORDER BY h.ord ASC
LIMIT 0 , 10



Как видите тут 3 лефтджойна. Их может быть больше. Они подключают много раз одну и ту же таблицу. В таблице этой может быть много данных и запрос из-за этого тормозит.

Вот структура таблицы cms3_hierarchy:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
CREATE TABLE `cms3_hierarchy` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `rel` int(10) unsigned NOT NULL,
  `type_id` int(10) unsigned NOT NULL,
  `lang_id` int(10) unsigned NOT NULL,
  `domain_id` int(10) unsigned NOT NULL,
  `obj_id` int(10) unsigned NOT NULL,
  `ord` int(11) DEFAULT '0',
  `tpl_id` int(10) unsigned DEFAULT NULL,
  `alt_name` varchar(128) DEFAULT NULL,
  `is_active` tinyint(1) DEFAULT NULL,
  `is_deleted` tinyint(1) DEFAULT NULL,
  `is_visible` tinyint(1) DEFAULT NULL,
  `updatetime` int(11) DEFAULT NULL,
  `is_default` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `types rels_FK` (`type_id`),
  KEY `Prefix from lang_id_FK` (`lang_id`),
  KEY `Domain from domain_id relation_FK` (`domain_id`),
  KEY `hierarchy to plain object image_FK` (`obj_id`),
  KEY `Getting template data_FK` (`tpl_id`),
  KEY `is_default` (`is_default`),
  KEY `alt_name` (`alt_name`),
  KEY `is_deleted` (`is_deleted`),
  KEY `is_active` (`is_active`),
  KEY `ord` (`ord`),
  KEY `rel` (`rel`),
  KEY `updatetime` (`updatetime`),
  KEY `is_visible` (`is_visible`),
  CONSTRAINT `FK_Domain from domain_id relation` FOREIGN KEY (`domain_id`) REFERENCES `cms3_domains` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_Getting template data` FOREIGN KEY (`tpl_id`) REFERENCES `cms3_templates` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_Prefix from lang_id` FOREIGN KEY (`lang_id`) REFERENCES `cms3_langs` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_hierarchy to plain object image` FOREIGN KEY (`obj_id`) REFERENCES `cms3_objects` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_types rels` FOREIGN KEY (`type_id`) REFERENCES `cms3_hierarchy_types` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=186 DEFAULT CHARSET=utf8;



cms3_objects

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE TABLE `cms3_objects` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `guid` varchar(64) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `is_locked` tinyint(1) DEFAULT NULL,
  `type_id` int(10) unsigned DEFAULT NULL,
  `owner_id` int(10) unsigned DEFAULT NULL,
  `ord` int(10) unsigned DEFAULT '0',
  `updatetime` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `Object to type relation_FK` (`type_id`),
  KEY `name` (`name`),
  KEY `owner_id` (`owner_id`),
  KEY `is_locked` (`is_locked`),
  KEY `ord` (`ord`),
  KEY `guid` (`guid`),
  KEY `updatetime` (`updatetime`),
  CONSTRAINT `FK_Object to type relation` FOREIGN KEY (`type_id`) REFERENCES `cms3_object_types` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=805 DEFAULT CHARSET=utf8;



cms3_object_content

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
CREATE TABLE `cms3_object_content` (
  `obj_id` int(10) unsigned DEFAULT NULL,
  `field_id` int(10) unsigned DEFAULT NULL,
  `int_val` bigint(20) DEFAULT NULL,
  `varchar_val` varchar(255) DEFAULT NULL,
  `text_val` mediumtext,
  `rel_val` int(10) unsigned DEFAULT NULL,
  `tree_val` int(10) unsigned DEFAULT NULL,
  `float_val` double DEFAULT NULL,
  KEY `Content to object relation_FK` (`obj_id`),
  KEY `Contents field id relation_FK` (`field_id`),
  KEY `Relation value reference_FK` (`rel_val`),
  KEY `content2tree_FK` (`tree_val`),
  KEY `int_val` (`int_val`),
  KEY `varchar_val` (`varchar_val`),
  KEY `float_val` (`float_val`),
  KEY `text_val` (`text_val`(8)),
  KEY `K_Complex_FieldIdAndRelVal` (`field_id`,`rel_val`),
  KEY `K_Complex_FieldIdAndTreeVal` (`field_id`,`tree_val`),
  KEY `K_Complex_ObjIdAndFieldId` (`obj_id`,`field_id`),
  CONSTRAINT `FK_Content to object relation` FOREIGN KEY (`obj_id`) REFERENCES `cms3_objects` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_Contents field id relation` FOREIGN KEY (`field_id`) REFERENCES `cms3_object_fields` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_Relation value reference` FOREIGN KEY (`rel_val`) REFERENCES `cms3_objects` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_content2tree` FOREIGN KEY (`tree_val`) REFERENCES `cms3_hierarchy` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



Как тут можно переписать запрос, чтобы он не тормозил?

У меня идея создать таблицу с контентом в которой все поля конкретного внутреннего типа в одной записи и упростить запрос до.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT DISTINCT SQL_CALC_FOUND_ROWS
    h.id AS id, h.rel AS pid
FROM
    cms3_hierarchy h,
    cms3_permissions p,
    (SELECT 
        id
    FROM
        kss_type_56 kt56in
    WHERE
        kt56in.fld_509 = '1'
            AND kt56in.fld_516 = '1'
            AND kt56in.fld_517 = '1') kt56
WHERE
    h.type_id IN (56) AND h.lang_id = '1'
        AND h.is_deleted = '0'
        AND h.is_active = '1'
        AND (p.rel_id = h.id AND p.level & 1
        AND p.owner_id IN (579))
        AND h.id = kt56.id
ORDER BY h.ord ASC
LIMIT 0 , 10



Подозреваю, что это будет выполняться значительно быстрее.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030699
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Prizzrak
Вот запрос который генерируется CMS на одном из блоков страницы
Ну у CMS вообще с оптимальностью туго - работая по ограниченному набору шаблонов, трудно создать нечто оптимальное. А переходить на чистый RAW SQL - нафига тогда она вообще нужна, эта CMS?
Prizzrak
Как тут можно переписать запрос, чтобы он не тормозил?

Заменяем
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
    ...
        LEFT JOIN
    cms3_object_content oc_509_lj ON oc_509_lj.obj_id = o.id
        AND oc_509_lj.field_id = '509'
        LEFT JOIN
    cms3_object_content oc_516_lj ON oc_516_lj.obj_id = o.id
        AND oc_516_lj.field_id = '516'
        LEFT JOIN
    cms3_object_content oc_517_lj ON oc_517_lj.obj_id = o.id
        AND oc_517_lj.field_id = '517'
WHERE
    ...
        AND ((oc_509_lj.int_val = '1'
        OR oc_516_lj.int_val = '1'
        OR oc_517_lj.int_val = '1'))


на
Код: sql
1.
2.
3.
4.
5.
6.
7.
    ...
        INNER JOIN
    cms3_object_content ON cms3_object_content.obj_id = o.id
WHERE
    ...
        AND cms3_object_content.field_id IN ('509', '516', '517')
        AND cms3_object_content.int_val = '1'


А ещё - смотрим на тип данных поля cms3_object_content.field_id , и если оно оказывается числовым, то заменяем список на числовой: (509, 516, 517) .
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030745
Prizzrak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina,

Дело в том, что в других подобных запросах может быть другое поле вместо int_val и значение там может быть другое. Потому да, конкретно этот запрос можно так ускорить, как Вы предложили. Но мне нужно универсальное решение. Потому я и хочу попробовать сделать вспомогательные таблицы и заполнять их с помощью триггеров.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030855
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Prizzrak,

А как часто изменяется информация в исходных таблицах?
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030882
Prizzrak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft
Prizzrak,

А как часто изменяется информация в исходных таблицах?


На этих трёх таблицах построена вся система. Данные в таблице cms3_hierarchy меняются когда создаётся или удаляется страница на сайте. Это происходит не очень часто. Если товары на сайт загружаются из внешнего источника и товарный состав часто меняется, то данные в этой табличке меняются при каждой синхронизации. Обычно это раз в сутки.

В табличке cms3_objects хранятся почти все сущности CMS. Это например заказы, адреса доставки и т.д. В этой табличке много данных и они меняются достаточно часто, при создании любой сущности на сайте.

Но самая нагруженная это табличкаcms3_object_content. В ней данные меняются при любом изменении данных на сайте. Скажем у товара поменялось описание данные в первых двух табличках не меняются, а в этой поменяются.

Я собираюсь не все изменения выгружать во вспомогательные таблицы. На сайте есть такие сущности, как типы данных. Они все свои данные хранят в этих вот таблицах, но используются они с разной частотой. Планирую вспомогательные таблицы использовать только для тех типов, которые участвуют в выборах и реально тормозят. Таких не много и они будут строиться на данных, которые меняются редко.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030927
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Prizzrak
Таких не много и они будут строиться на данных, которые меняются редко.
Тогда, возможно, вспомогательные таблицы лучше заполнять не триггерами позаписно, а пакетно, например, раз в сутки ночью ?
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030933
Prizzrak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft
Prizzrak
Таких не много и они будут строиться на данных, которые меняются редко.
Тогда, возможно, вспомогательные таблицы лучше заполнять не триггерами позаписно, а пакетно, например, раз в сутки ночью ?


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

Мне пока так и не ответили, почему лучше их не использовать для данной задачи.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030937
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Prizzrak
Мне пока так и не ответили, почему лучше их не использовать для данной задачи.
Для данной задачи не знаю, а общие недостатки сохраняются - увеличивается время модификации таблиц, триггера не срабатывают при каскадном срабатывании внешних ключей.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030944
Prizzrak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft
Prizzrak
Мне пока так и не ответили, почему лучше их не использовать для данной задачи.
Для данной задачи не знаю, а общие недостатки сохраняются - увеличивается время модификации таблиц, триггера не срабатывают при каскадном срабатывании внешних ключей.

Время модификации таблицы - это понятно. Надо просто померить. Триггеры планирую сделать простые и не ресурсоёмкие.

Вот с каскадными ключами у меня вопрос. Вот каскадный констрейнт:

Код: sql
1.
CONSTRAINT `FK_Content to object relation` FOREIGN KEY (`obj_id`) REFERENCES `cms3_objects` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,



Я верно понял, что он означает что если в таблице cms3_objects поменяется значение в поле id, то в текущей таблице оно тоже поменяется в поле obj_id, а если строка из таблицы cms3_objects удалится, то из текущей таблицы тоже должны удалиться все строки в которых obj_id=id? И второй вопрос: В случае описанных выше изменений не сработают триггеры на текущей таблице, но на таблице cms3_objects её триггеры сработают? Если всё так, то это не проблема. Это конечно надо учесть, но это не проблема.
...
Рейтинг: 0 / 0
Поговорим о триггерах
    #40030991
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Prizzrak
Я верно понял, что он означает что если в таблице cms3_objects поменяется значение в поле id, то в текущей таблице оно тоже поменяется в поле obj_id, а если строка из таблицы cms3_objects удалится, то из текущей таблицы тоже должны удалиться все строки в которых obj_id=id? И второй вопрос: В случае описанных выше изменений не сработают триггеры на текущей таблице, но на таблице cms3_objects её триггеры сработают?
Вроде все верно, если я ничего не упустил.

В доке написано довольно скупо, без подробостей:
https://dev.mysql.com/doc/refman/8.0/en/stored-program-restrictions.html#stored-routines-trigger-restrictions Triggers are not activated by foreign key actions.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Поговорим о триггерах
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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