Как оптимизировать представления MySQL
-
06-07-2019 - |
Вопрос
У меня есть несколько запросов, использующих представления, и они выполняются намного медленнее, чем я ожидал бы, учитывая, что все соответствующие таблицы проиндексированы (и в любом случае не такие большие).
Я надеюсь, что смогу это объяснить:
Мой основной запрос выглядит следующим образом (сильно упрощенный)
select [stuff] from orders as ord
left join calc_order_status as ors on (ors.order_id = ord.id)
calc_order_status
это представление, определенное таким образом:
create view calc_order_status as
select ord.id AS order_id,
(sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total
from orders ord
left join order_items itm on itm.order_id = ord.id
group by ord.id
Заказы (ord) содержат заказы, order_items
содержат отдельные товары, связанные с каждым заказом, и их цены.
Все таблицы правильно проиндексированы, НО все работает медленно, и когда я делаю ОБЪЯСНЕНИЕ, я получаю
# id select_type table type possible_keys key key_len ref rows Extra
1 1 PRIMARY ord ALL customer_id NULL NULL NULL 1002 Using temporary; Using filesort
2 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1002
3 1 PRIMARY cus eq_ref PRIMARY PRIMARY 4 db135147_2.ord.customer_id 1 Using where
4 2 DERIVED ord ALL NULL NULL NULL NULL 1002 Using temporary; Using filesort
5 2 DERIVED itm ref order_id order_id 4 db135147_2.ord.id 2
Я предполагаю, что "derived2" относится к представлению.Отдельные элементы (itm), похоже, работают нормально, индексируются по order _ id.Проблема, по-видимому, в строке # 4, которая указывает на то, что система не использует ключ для таблицы заказов (ord).Но в ОСНОВНОМ запросе идентификатор заказа уже определен:слева присоедините calc_order_status к ors on (ors.order _ id = ord.id) и ord.id (как в основном запросе, так и в представлении) ссылаются на первичный ключ.
Я где-то читал, что MySQL simpliy не так хорошо оптимизирует представления и может не использовать ключи при некоторых условиях, даже когда они доступны.Похоже, это один из таких случаев.
Я был бы признателен за любые предложения.Есть ли способ заставить MySQL осознать, что "все проще, чем вы думаете, просто используйте первичный ключ, и все будет в порядке"?Или взгляды - это вообще неправильный способ решения этой проблемы?
Решение
Если это вообще возможно, удалите эти соединения, удалите их.Замена их вложенными запросами значительно ускорит процесс.
вы также могли бы попробовать запустить что-то подобное, чтобы посмотреть, есть ли у него вообще какая-либо разница в скорости.
select [stuff] from orders as ord
left join (
create view calc_order_status as
select ord.id AS order_id,
(sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total
from orders ord
left join order_items itm on itm.order_id = ord.id
group by ord.id
) as ors on (ors.order_id = ord.id)
Другие советы
Индекс полезен для поиска нескольких строк в большой таблице, но когда вы запрашиваете каждую строку, индекс просто замедляет работу.Итак, здесь MySQL, вероятно, ожидает использования всей таблицы [order], поэтому лучше не использовать индекс.
Вы можете попробовать, если это будет быстрее с помощью принуждение MySQL для использования индекса:
from orders as ord force index for join (yourindex)