powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация тяжелого SQL запроса MySQL
23 сообщений из 23, страница 1 из 1
Оптимизация тяжелого SQL запроса MySQL
    #39630213
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток.

Есть такой запрос:

Код: 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.
SELECT tsc.Id, min(spc.sDate)
FROM TEST.`Services` tsc,
(
    select /*+ SUBQUERY(MATERIALIZATION) */ ss.SERVICE_ID , spp.plan_id, spp.ChangesStartTime, spp.changeDate
    from (
        select sp.ChangesStartTime, sp.changeDate, -1 as plan_id, sp.ServiceCode
            from DICT.Price sp
            where sp.PriceChangeId > ?
            and sp.PlanCode = ''
        union
        select sp.ChangesStartTime, sp.changeDate, tp.plan_id as plan_id, sp.ServiceCode
            from DICT.Price sp
            join DICT.Plan btp on btp.CODE = sp.PlanCode
            join DICT.Plan tp on tp.BASIC_PLAN_ID = btp.PLAN_ID
            where sp.PriceChangeId > ?
            and sp.PlanCode != ''
            and sp.BaseTariffPlan = 1
        union
        select sp.ChangesStartTime, sp.changeDate, tp.plan_id as plan_id, sp.ServiceCode
            from DICT.Price sp
            join DICT.Plan tp on tp.CODE = sp.PlanCode
            where sp.PriceChangeId > ?
            and sp.PlanCode != ''
        ) spp
    join DICT.Service_f ss on ss.SERVICE_CODE = spp.ServiceCode
) spc
where tsc.serviceId = spc.service_id
and tsc.plnId = if(spc.plan_id = -1, tsc.plnId, spc.plan_id)
and tsc.serviceDateFrom > GREATEST(spc.ChangesStartTime, spc.changeDate)
group by tsc.Id;



План запроса печальный (во вложении).
Периодически отваливается по таймауту (запрос вызывается из Java кода):
Код: java
1.
2.
Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback;



Движок NDB. Возможно ли как-то оптимизировать данный запрос?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630225
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3,

В запросе точно нужны именно UNION, а не UNION ALL ?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630231
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и тотальное отсутствие индексов выглядит странно.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630234
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft,
miksoftВ запросе точно нужны именно UNION, а не UNION ALL ?
Это сильно может повлиять на производительность?
miksoftНу и тотальное отсутствие индексов выглядит странно.
Согласен, только не пойму на какие поля их надо навесить?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630237
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft В запросе точно нужны именно UNION, а не UNION ALL ?
UNION ALL оставляет дубликаты
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630243
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3miksoftВ запросе точно нужны именно UNION, а не UNION ALL ?
UNION ALL оставляет дубликатыОставлять-то оставляет. Но есть ли они по факту? И мешают ли они, если есть?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630244
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Опишите вообще словами полностью смысл этого запроса.
У меня есть ощущение, что его можно переписать намного короче и быстрее.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630252
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftsergey-iv3пропущено...

UNION ALL оставляет дубликатыОставлять-то оставляет. Но есть ли они по факту? И мешают ли они, если есть?

По факту они есть. Если использовать просто UNION, то такой запрос:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
select count(*) from (
       select sp.ChangesStartTime, sp.changeDate, -1 as plan_id, sp.ServiceCode
            from DICT.Price sp
            where sp.PriceChangeId > ?
            and sp.PlanCode = ''
        union
        select sp.ChangesStartTime, sp.changeDate, tp.plan_id as plan_id, sp.ServiceCode
            from DICT.Price sp
            join DICT.Plan btp on btp.CODE = sp.PlanCode
            join DICT.Plan tp on tp.BASIC_PLAN_ID = btp.PLAN_ID
            where sp.PriceChangeId > ?
            and sp.PlanCode != ''
            and sp.BaseTariffPlan = 1
        union
        select sp.ChangesStartTime, sp.changeDate, tp.plan_id as plan_id, sp.ServiceCode
            from DICT.Price sp
            join DICT.Plan tp on tp.CODE = sp.PlanCode
            where sp.PriceChangeId > ?
            and sp.PlanCode != ''
        ) as cnt;


вернет 13834 записи. Тогда как UNION ALL возвращает 28870. Они мешают, т.к. они попадут в результирующую выборку (SELECT tsc.Id, min(spc.sDate) ...).

Словами описать не смогу, т.к. сам писал его не я, а досталось наследство, с задачей, устранить ошибку с таймаутом.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630259
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3вернет 13834 записи. Тогда как UNION ALL возвращает 28870. Они мешают, т.к. они попадут в результирующую выборку (SELECT tsc.Id, min(spc.sDate) ...).Как же они попадут, если в результирующей выборке группировка?
Попробуйте, результат всего запроса меняется, если заменить UNION на UNION ALL ?

Насчет индексов - попробуйте индекс на таблице DICT.Price из поля PriceChangeId.
После создания индекса сделайте OPTIMIZE TABLE DICT.Price
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630278
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftsergey-iv3вернет 13834 записи. Тогда как UNION ALL возвращает 28870. Они мешают, т.к. они попадут в результирующую выборку (SELECT tsc.Id, min(spc.sDate) ...).Как же они попадут, если в результирующей выборке группировка?
Попробуйте, результат всего запроса меняется, если заменить UNION на UNION ALL ?


Нет, результат не поменялся. Только сейчас я тестирую на другой базе, где меньше данных.

miksoftНасчет индексов - попробуйте индекс на таблице DICT.Price из поля PriceChangeId.
После создания индекса сделайте OPTIMIZE TABLE DICT.Price

Добавил индекс:

Код: sql
1.
CREATE INDEX PriceChangeId ON DICT.Price (PriceChangeId) USING BTREE;



План запроса такой. Тестирую на другой базе с такой же структурой. Не понятно, почему он отличается от первоначального:
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630279
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В том посте случайно выложил старый план. Вот после добавления индекса:
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630281
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3Вот после добавления индекса:А как время выполнения запроса изменилось?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630287
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftsergey-iv3Вот после добавления индекса:А как время выполнения запроса изменилось?
По факту нет, без индекса и с union отработал за 17.83, с индексом и union all за 17.37 в тестовой таблице TEST.`Services` tsc - 9076 записей, в реале 2 млн.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630288
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft, и почему-то после добавления индекса, в плане type все равно остался ALL
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630289
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3Словами описать не смогу, т.к. сам писал его не я, а досталось наследство, с задачей, устранить ошибку с таймаутом.
Дружище. Послушай совет. Я не разбираюсь в MySQL. Я по другой части.
Но ты не можешь "устранять ошибку" (а если быть точным то это не ошибка
а performance issue) без понимания задачи с точки зрения бизнеса.

Механическая оптимизация может привести к другим последствиям.
Например отчот выдаст неверные данные. Более того.. он может
выдать верные данные сейчас. Но это не будет формальным доказательством
его правоты вообще. Может быть баг на других исходных.

Смотри у тебя 3 справочника Price, Plan, Service соединяются сложным образом
чтобы получить Id-шники и минимальные даты. Подумай в чем их бизнес-смысл.
Найти самую неэффективную выборку. У тебя есть как минимум 3 независимых
под-запроса. Какой из них самый медленный? Определи и займись только им.
По топику тебе дали совет построить инексы. Построй по всем ключам где есть
соединение. Как минимум primary и foreign должны быть всегда.

Фильтр по справочнику цен PriceChangeId > ? у тебя повторяется трижды.
Материализуй его результат. Ну и сделай UNION ALL как советуют.

Попробуй. У тебя получится.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630297
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3в тестовой таблице TEST.`Services` tsc - 9076 записей, в реале 2 млн.Так не получится. Применение индексов сильно зависит от статистики данных.
Приводите тестовые данные в соответствие с реальными.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630299
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3miksoft, и почему-то после добавления индекса, в плане type все равно остался ALLДа, а колонка KEY пуста, значит индекс не применяется.
Сколько записей в таблице DICT.Price и сколько из них выбирает условие sp.PriceChangeId > ?
Что подставляется вместо знака вопроса?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630302
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftsergey-iv3miksoft, и почему-то после добавления индекса, в плане type все равно остался ALLДа, а колонка KEY пуста, значит индекс не применяется.
Сколько записей в таблице DICT.Price и сколько из них выбирает условие sp.PriceChangeId > ?
Что подставляется вместо знака вопроса?

16067 записей. Выбирается, около 500 записей. Вместо знака вопроса подставляется число, например:
Код: sql
1.
select * from DICT.Price sp where sp.PriceChangeId > 53000 ;
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630306
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv316067 записей. Выбирается, около 500 записей.Это немногим более 3% - близко к пограничной величине для применения индекса, хотя и ниже ее.
Но в плане колонка filtered больше, т.е. собранная статистика не соответствует факту. Поэтому я и говорил, что после создания индекса желательно сделать ANALYZE TABLE или OPTIMIZE TABLE, чтобы в т.ч. и статистику пересчитать.

Но лучше все-таки довести данные до реальных. Тогда, подозреваю, эта доля изменится.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630325
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft, а вообще можно как-то избавится от derived table которая во FROM: SELECT tsc.Id, min(spc.sDate)
FROM TEST.`Services` tsc, ( ...), как-то заменить это?
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630330
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sergey-iv3miksoft, а вообще можно как-то избавится от derived table которая во FROM: SELECT tsc.Id, min(spc.sDate)
FROM TEST.`Services` tsc, ( ...), как-то заменить это?Можно, если переписать запрос так, чтобы в нем не было подзапросов. Но особого смысла в этом нет. Да и невозможно, не зная его логики.

Избавляться надо от других вещей, от using filesort, например.
Или добиваться использования индексов там, где это имеет смысл.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630349
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторИзбавляться надо от других вещей, от using filesort, например.

он там все 2 миллиона группирует.
...
Рейтинг: 0 / 0
Оптимизация тяжелого SQL запроса MySQL
    #39630378
sergey-iv3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftИзбавляться надо от других вещей, от using filesort, например.
Согласен. Но для этого нужно избавится от group by. А от него не избавиться, тк используется агрегатная функция min.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация тяжелого SQL запроса MySQL
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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