2016-12-12 4 views
2

У меня возникла проблема с MySQL JOIN и SUM. Поскольку мой JOIN имеет несколько совпадений, я сделаю SELECT в JOIN, поэтому он не будет судить о многом.Проблема с MySQL JOIN и SUM

Проблема:
Мой запрос очень медленный. В тестовой настройке ниже он работает всего за 1 мс без каких-либо индексов. Но в моей производственной базе данных этот запрос занимает ~ 4 секунды при выборе только одной записи (WHERE id = X).

Таблица а имеет ~ 700.000 записей
Таблица B имеет ~ 800.000 записей
Таблица С имеет ~ 45.000 записей

Таблица а имеет индекс по id
Таблица B имеет индекс на id, a_id
таблица C имеет индекс на id, a_id

Ниже упрощенных таблиц и используемых запросов.

Таблица a

id 
--- 
1 

Таблица b

id | a_id | amount | price 
-------------------------- 
1 | 1 |  1 | 25 
2 | 1 |  1 | 20 

Таблица c

id | a_id | amount | price 
-------------------------- 
1 | 1 |  1 | 23 
2 | 1 |  1 | 20 

запрос:
Теперь, когда я запускаю этот запрос, чтобы получить сумму b и c, которые имеют ссылку в таблице a.

SELECT id, bPrice, cPrice 
FROM a 
LEFT JOIN (SELECT a_id, SUM(amount * price) AS bPrice FROM b GROUP BY a_id) bb ON a.id = bb.a_id 
LEFT JOIN (SELECT a_id, SUM(amount * price) AS cPrice FROM c GROUP BY a_id) cc ON a.id = cc.a_id 

Неправильный результат, но быстро

SELECT 
    a.id, 
    SUM(b.amount * b.price) AS bPrice, 
    SUM(c.amount * c.price) AS cPrice 
FROM a 
JOIN b ON a.id = b.a_id 
JOIN c ON a.id = c.a_id; 

SQL Fiddle example

+0

Нет индексов на 'a_id' либо' 'b' или c'? – eggyal

ответ

0

Попробуйте следующий запрос:

select set1.id,set1.bPrice,set2.cPrice from (SELECT a.id,SUM(b.amount * b.price) AS bPrice FROM a JOIN b ON a.id = b.a_id) as set1 
JOIN 
(SELECT a.id,SUM(c.amount * c.price) AS cPrice FROM a JOIN c ON a.id = c.a_id) as set2 ON set1.id = set2.id 
+0

Этот запрос также работает через ~ 4 секунды, поэтому не быстрее. Также я добавил 'GROUP BY a.id' к запросам JOIN – Timo002

2

MySQL будет бороться, чтобы тянуть индекс через от вложенных запросов, чтобы присоединиться к , и подозреваете, что вы присоединяетесь к LOT строк из подзапросов.

В качестве начального шага вы можете попробовать удалить один из подзапросов, чтобы просто изменить его на соединение с основной таблицей.

SELECT id, 
     SUM(b.amount * b.price) AS bPrice, 
     cPrice 
FROM a 
LEFT OUTER JOIN b ON a.id = b.a_id 
LEFT OUTER JOIN 
(
    SELECT a_id, 
      SUM(amount * price) AS cPrice 
    FROM c 
    GROUP BY a_id 
) cc ON a.id = cc.a_id 
GROUP BY a.id, 
     cc.cPrice 
+0

Этот запрос не работает, см. Последнюю строку' cc.cPrice' – Timo002

+0

Пропущенная запятая. Исправлено: – Kickstart

+0

ОК, это работает в ~ 80 мс, когда я также добавляю 'WHERE a.id = '''.Когда я запускаю всю базу данных, 800 тыс. Записей, она работает через ~ 9 секунд. Для всех записей 800 тыс. Это приемлемо, и для одной записи 80 мс также приемлемо, начиная с 4000 мс! Tnx! – Timo002

0

Может быть стоит попробовать подзапроса - иногда они могут быть быстрее:

SELECT 
    id, 
    (SELECT SUM(amount * price) AS bPrice FROM b where b.a_id = a.id) AS bPrice, 
    (SELECT SUM(amount * price) AS cPrice FROM c where c.a_id = a.id) AS cPrice 
FROM a