У меня есть запрос, который я пытаюсь ускорить. Я уверен, что есть способ сделать это более эффективным, но у меня недостает знаний.Запрос MySQL с зависимыми подзапросами - как я могу ускорить его?
заказов - это показывает, одна строки за заказ получена (в настоящее время 800000 строк)
orders_financials - это показывает, по одной строке на финансовую операцию, связанную с порядком (в настоящее время 2000000 строк)
В таблице orders_financials будет содержать несколько строк на заказ, категория сделки показана на financialType
Так, например, для одного заказа там может быть 5 строк в orders_financials
financialType = 14: value = 10.00
financialType = 12: value = 7.00
financialType = 18: value = 2.50
financialType = 15: value = 0.30
financialType = 17: value = 7.50
Для каждого заказа будет различный объем данных. Со временем в систему добавляется больше данных, и новые ряды добавляются в order_financial.
Что я пытаюсь сделать, так это запустить запрос, который позволяет мне получить одну строку за заказ и для этой строки рассчитать суммы нескольких категорий финансовых транзакций.
Запрос ниже должен дать мне все заказы, размещенные CUSTOMERID 279:
select
orders.orderID,
customers.username,
(select group_concat(financialRef) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (17)) ref,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (17)) costs_cost,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (12,13)) costs_exp,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (14)) costs_sell,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (15)) costs_sell_out,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (1,2,3,9,11)) extras_in,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (4,5)) extras_out,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (20)) extras_back,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (18)) insurance_in,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (10,6)) insurance_out,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (19)) insurance_back
from orders
left join customers on orders.customerID=customers.customerID
where customers.customerID='279'
order by orderID
(FYI, есть 18,263 записей в таблице заказов, где CUSTOMERID = 279)
Вы увидите, что financialType-х из 12 или 13 можно суммировать с cost_exp. Аналогично 1,2 3,9,11 - все extras_in.
Конечный результат - это хороший запрос с большим количеством данных, но он дает подробный обзор для каждого заказа. В том месте, где я могу искать по клиенту, по сервису, по диапазону дат и т. Д.
Моя проблема заключается в том, что для этого запроса требуется лет. Я должен делать это очень неэффективно, так как каждый элемент запроса индивидуально выполняется быстро.
Из лога медленного я могу видеть это перебором 422,000,000 строк
Query_time: 528.107584 Lock_time: 0.000652 Rows_sent: 1388 Rows_examined: 422442417
Там должна быть более эффективным способом, но я изо все силы, чтобы увидеть.
EDIT - Вот EXPLAIN вышеуказанного запроса:
+----+--------------------+-------------------+-------+-----------------------+---------------+---------+---------------------------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------------------+-------+-----------------------+---------------+---------+---------------------------+--------+--------------------------+
| 1 | PRIMARY | customers | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 1 | PRIMARY | orders | ref | customerID | customerID | 5 | const | 24802 | Using where; Using index |
| 12 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | financialType | 4 | const | 1 | Using where |
| 11 | DEPENDENT SUBQUERY | orders_financials | range | orderID,financialType | financialType | 4 | NULL | 2 | Using where |
| 10 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | financialType | 4 | const | 49717 | Using where |
| 9 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | financialType | 4 | const | 1 | Using where |
| 8 | DEPENDENT SUBQUERY | orders_financials | range | orderID,financialType | financialType | 4 | NULL | 2 | Using where |
| 7 | DEPENDENT SUBQUERY | orders_financials | range | orderID,financialType | financialType | 4 | NULL | 5 | Using where |
| 6 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | financialType | 4 | const | 139 | Using where |
| 5 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | orderID | 4 | p4db_admin.orders.orderID | 236338 | Using where |
| 4 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | orderID | 4 | p4db_admin.orders.orderID | 236338 | Using where |
| 3 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | financialType | 4 | const | 99966 | Using where |
| 2 | DEPENDENT SUBQUERY | orders_financials | ref | orderID,financialType | financialType | 4 | const | 99966 | Using where |
+----+--------------------+-------------------+-------+-----------------------+---------------+---------+---------------------------+--------+--------------------------+
13 rows in set (0.00 sec)
показать нам объяснить этот запрос. Также подзапрос в mysql - это, как правило, очень медленная и болезненная вещь, поэтому, если вы собираетесь использовать их много, подумайте о переключении на mariadb. –
Какие индексы у вас есть на таблицах? –
Попробуйте добавить составной индекс на '(orderID, financialType, financialRef, amount)', а затем и ваш запрос, и переписать на @ 491243 –