Оптимизация точного количества отфильтрованных страниц (COUNT(*)) в MySQL с помощью динамических фильтров JSON в Spring MySql

Форум по Mysql
Ответить
Anonymous
 Оптимизация точного количества отфильтрованных страниц (COUNT(*)) в MySQL с помощью динамических фильтров JSON в Spring

Сообщение Anonymous »

Постановка проблемы:

Мы используем API разбиения на страницы Java/Spring GET/POST getAll поверх MySQL в AWS RDS и нам нужна помощь в оптимизации точного отфильтрованного количества
Текущее состояние:

Основной набор данных — курсы с реляционными столбцами, такими как id, tenant_id, созданный_by, созданный_at, обновленный_at, удаленный_at плюс документ значений_json, содержащий такие ключи, как имя, псевдоним, уровень, страна, валюта, символ_валюты, название отдела, международный_студент, внутренний_студент, код_курса, экстракция_дата и институты;

В нашем потоке getAll (/models/get/courses) мы всегда выполняем как countQuery, так и selectQuery (для строгих метаданных Spring с разбивкой на страницы), с динамическими фильтрами, разрешенными для столбцов таблицы и произвольными Ключи JSON
Причина:

Текущим узким местом задержки является запрос подсчета, который может занять ~35–39 секунд для некоторых фильтров (особенно предикатов типа LIKE/contains над выражениями JSON), тогда как выбор выполняется сравнительно быстро;

Размер таблицы составляет около 327 406 строк;
Как выглядят запросы на подсчет и выбор:

Запрос на подсчет:

SELECT count(*) FROM devdts.courses s WHERE (s.tenant_id IS NULL OR s.tenant_id = 'abcd') AND s.deleted_at IS NULL AND ((((LOWER(CAST(JSON_UNQUOTE(COALESCE(JSON_EXTRACT(s.values_json, '$.institutes.id'), JSON_EXTRACT(s.values_json, '$.institutes'), JSON_EXTRACT(s.values_json, '$.institutes'))) AS CHAR)) LIKE :institutes_is_any_of_0_96c54c95_c730_4bec_b63d_08d98f643553))))

Выберите запрос:
SELECT s.*, JSON_SET(s.values_json, '$.institute_rank', IFNULL(JSON_MERGE_PATCH(JSON_OBJECT('id', u_institute_rank.id), IFNULL(u_institute_rank.values_json, JSON_OBJECT())), JSON_OBJECT('id', u_institute_rank.id)), '$.institutes', IFNULL(JSON_MERGE_PATCH(JSON_OBJECT('id', u_institutes.id), IFNULL(u_institutes.values_json, JSON_OBJECT())), JSON_OBJECT('id', u_institutes.id)), '$.created_by', JSON_OBJECT('id', u_created_by.id, 'name', u_created_by.name)) AS courses FROM devdts.courses s LEFT JOIN devdts.institutes u_institute_rank ON u_institute_rank.id = JSON_UNQUOTE(JSON_EXTRACT(s.values_json, '$.institute_rank')) LEFT JOIN devdts.institutes u_institutes ON u_institutes.id = JSON_UNQUOTE(JSON_EXTRACT(s.values_json, '$.institutes')) LEFT JOIN devdts.users u_created_by ON u_created_by.id = s.created_by WHERE (s.tenant_id IS NULL OR s.tenant_id = 'abcd') AND s.deleted_at IS NULL

Это запросы с минимальными фильтрами, их может быть несколько как для ключей, так и для столбцов JSON.
Что мы пробовали:

Я уже пробовал инструменты SQL/синхронизации с идентификаторами трассировки, удаляя ненужные LEFT JOIN из подсчета курсов, добавляя составной индекс (deleted_at, tenant_id) и ужесточая некоторые фильтры на основе идентификаторов, которые частично помогли, но не помогли. Задержка подсчета LIKE-on-JSON;
Я попробовал удалить левые соединения, и запрос стал таким:

SELECT count(*) FROM devdts.courses s WHERE (s.tenant_id IS NULL OR s.tenant_id = 'abcd') AND s.deleted_at IS NULL AND ((((LOWER(CAST(JSON_UNQUOTE(COALESCE(JSON_EXTRACT(s.values_json, '$.institutes.id'), JSON_EXTRACT(s.values_json, '$.institutes'), JSON_EXTRACT(s.values_json, '$.institutes'))) AS CHAR)) LIKE '%96c54c95-c730-4bec-b63d-08d98f643553%'))))

Все еще требуется время
Требуется помощь в отношении:

Я знаю, что мы пытаемся использовать функции NoSql в пространстве MySql, но у нас много таблиц, около 30, и все они имеют одну и ту же структуру столбцов таблицы, чтобы сделать API универсальными, поэтому необходимо решение относительно этой архитектуры.
Редактирование:
Хотелось бы добавить более подробную информацию о таблица, ее индексы и то, как выглядит строка данных о единицах.
Это все столбцы таблицы курса:
Изображение

Это текущие значения:
Изображение

Вот как выглядят данные:
# id values_json created_at created_by updated_at deleted_at university_id description name university course_fee_virtual institutes tenant_id alias_virtual country_virtual course_name_virtual institutes_virtual
00003b98-1f43-4603-beae-773780fc1405 {"name":"Doctor of Philosophy in Classics","about":"At Parturient Porta Vestibulum Integer Sociosqu Vitae Aptent Aptent Praesent Rhoncus Urna","alias":"doctor-of-philosophy-in-classics","level":"postgraduate","country":"united_states","currency":"USD","currency_symbol":"$","department_name":"historical_philosophical_and_religious_studies","international_student":"false","domestic_student":"false","extraction_date":"2025-08-07T06:30:00.000Z","institutes":"af7cf533-8ad7-4f68-9f26-c0dd7fd5052e","course_link":"https://www.classics.pitt.edu/graduate/ ... philosophy"} 2025-09-29 14:23:04 2025-12-28 09:35:58 af7cf533-8ad7-4f68-9f26-c0dd7fd5052e af7cf533-8ad7-4f68-9f26-c0dd7fd5052e doctor-of-philosophy-in-classics united_states doctor of philosophy in classics af7cf533-8ad7-4f68-9f26-c0dd7fd5052e


Подробнее здесь: https://stackoverflow.com/questions/798 ... namic-json
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «MySql»