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

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

Код: 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
14.04.2018, 13:50
    #39630225
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
sergey-iv3,

В запросе точно нужны именно UNION, а не UNION ALL ?
...
Рейтинг: 0 / 0
14.04.2018, 14:04
    #39630231
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
Ну и тотальное отсутствие индексов выглядит странно.
...
Рейтинг: 0 / 0
14.04.2018, 14:16
    #39630234
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
miksoft,
miksoftВ запросе точно нужны именно UNION, а не UNION ALL ?
Это сильно может повлиять на производительность?
miksoftНу и тотальное отсутствие индексов выглядит странно.
Согласен, только не пойму на какие поля их надо навесить?
...
Рейтинг: 0 / 0
14.04.2018, 14:38
    #39630237
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
miksoft В запросе точно нужны именно UNION, а не UNION ALL ?
UNION ALL оставляет дубликаты
...
Рейтинг: 0 / 0
14.04.2018, 15:07
    #39630243
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
sergey-iv3miksoftВ запросе точно нужны именно UNION, а не UNION ALL ?
UNION ALL оставляет дубликатыОставлять-то оставляет. Но есть ли они по факту? И мешают ли они, если есть?
...
Рейтинг: 0 / 0
14.04.2018, 15:14
    #39630244
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
Опишите вообще словами полностью смысл этого запроса.
У меня есть ощущение, что его можно переписать намного короче и быстрее.
...
Рейтинг: 0 / 0
14.04.2018, 15:32
    #39630252
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
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
14.04.2018, 15:43
    #39630259
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
sergey-iv3вернет 13834 записи. Тогда как UNION ALL возвращает 28870. Они мешают, т.к. они попадут в результирующую выборку (SELECT tsc.Id, min(spc.sDate) ...).Как же они попадут, если в результирующей выборке группировка?
Попробуйте, результат всего запроса меняется, если заменить UNION на UNION ALL ?

Насчет индексов - попробуйте индекс на таблице DICT.Price из поля PriceChangeId.
После создания индекса сделайте OPTIMIZE TABLE DICT.Price
...
Рейтинг: 0 / 0
14.04.2018, 17:22
    #39630278
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
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
14.04.2018, 17:22
    #39630279
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
В том посте случайно выложил старый план. Вот после добавления индекса:
...
Рейтинг: 0 / 0
14.04.2018, 17:34
    #39630281
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
sergey-iv3Вот после добавления индекса:А как время выполнения запроса изменилось?
...
Рейтинг: 0 / 0
14.04.2018, 18:21
    #39630287
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
miksoftsergey-iv3Вот после добавления индекса:А как время выполнения запроса изменилось?
По факту нет, без индекса и с union отработал за 17.83, с индексом и union all за 17.37 в тестовой таблице TEST.`Services` tsc - 9076 записей, в реале 2 млн.
...
Рейтинг: 0 / 0
14.04.2018, 18:23
    #39630288
sergey-iv3
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
miksoft, и почему-то после добавления индекса, в плане type все равно остался ALL
...
Рейтинг: 0 / 0
14.04.2018, 18:32
    #39630289
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация тяжелого SQL запроса MySQL
sergey-iv3Словами описать не смогу, т.к. сам писал его не я, а досталось наследство, с задачей, устранить ошибку с таймаутом.
Дружище. Послушай совет. Я не разбираюсь в MySQL. Я по другой части.
Но ты не можешь "устранять ошибку" (а если быть точным то это не ошибка
а performance issue) без понимания задачи с точки зрения бизнеса.

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

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

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

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

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

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

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

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


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