2016-02-05 4 views
0

У меня есть MySQL базу данных с помощью таблицы, которая имеет следующие столбцы ..Можно ли оптимизировать этот запрос?

id 
dealerId 
month_year 
total_price 
total_count 
vin_prefix 

и таблица имеет 20 миллионов записей, я хочу, чтобы получить сумму (TOTAL_PRICE) всех этих автомобилей, проданных дилером с ID # 02 (это довольно просто)

Однако, я хочу, чтобы получить сумму всех других дилеров, которые продали свои машины с таким же vin_prefix, как дилер # 02

так я написал этот запрос ...

SELECT d.dealerId 
    FROM `dealer_monthly_report` d 
    where d.dealerId <> 2 
     and d.vin_prefix in (select distinct(d2.vin_prefix) 
           from `dealer_monthly_report` d2 
           where d2.dealerId = 2) 
    group by d.dealerId 

Но можем ли мы оптимизировать этот запрос в любом случае? Индексы использовались отдельно для дилеров, vin_prefix и month_year.

Спасибо!

+0

Distinct действительно не нужны в вашем В запросе. Может быть лучше без него – JamieD77

+0

По-прежнему слишком медленно ... –

ответ

0

Да, возможно, это возможно. Это ваш запрос:

SELECT d.dealerId 
FROM `dealer_monthly_report` d 
WHERE d.dealerId <> 2 AND 
     d.vin_prefix in (select distinct d2.vin_prefix 
         from `dealer_monthly_report` d2 
         where d2.dealerId = 2 
        ) 
GROUP BY d.dealerId; 

Я бы переписать запрос с использованием exists:

SELECT d.dealerId 
FROM `dealer_monthly_report` d 
WHERE d.dealerId <> 2 AND 
     EXISTS (select 1 
       from `dealer_monthly_report` d2 
       where d2.dealerId = 2 and d.vin_prefix = d2.vin_prefix 
      ) 
GROUP BY d.dealerId; 

Затем индексы на dealer_monthly_report(dealerId) и dealer_monthly_report(vin_prefix, dealerId) лучше всего подходят для работы.

Если у вас есть таблица дилеров с vin_prefix, то лучший подход не имеет group by вообще:

select dealerId d 
from dealers d 
where dealerid <> 2 and 
     exists (select d2.vin_prefix 
       from `dealer_monthly_report` dmr 
       where d2.dealerId = 2 and dmr.vin_prefix = d.vin_prefix 
      ); 

Это будет использовать индекс по dealer_monthly_report(vin_prefix, dealerId) и dealers(dealerid, vin_prefix).

+0

спасибо @gordon Я собираюсь попробовать это –

1

Просто попробовал ваш запрос и запрос Гордона с 1.000.000 записями. Добавив индекс dealer_monthly_report(vin_prefix, dealerId), ваш предложенный запрос кажется немного быстрее, чем у Гордона (около 1-2 секунд для моих записей).

Edit: исправлен код для временной таблицы

Я хотел бы предложить продлить первое решение от Гордона следующим образом:

CREATE TEMPORARY TABLE vin_prefixes_dealerID_2 
    SELECT distinct(d.vin_prefix) as vin_prefix 
    FROM `dealer_monthly_report` d 
    WHERE d.dealerID = 2 
; 

SELECT d.dealerId, sum(total_price) 
FROM `dealer_monthly_report` d 
WHERE d.dealerId <> 2 AND 
EXISTS (
    SELECT 1 
    FROM `vin_prefixes_dealerID_2` d2 
    where d.vin_prefix = d2.vin_prefix 
) 
GROUP BY d.dealerId; 

Это уменьшило время запроса от первоначальных 18-20 секунд до 6-7 секунд (для 1.000.000 записей)

Редактировать: исправлена ​​альтернативный подход

Альтернативный подход может быть:

CREATE TEMPORARY TABLE vin_prefixes_dealerID_2 
    SELECT distinct(d.vin_prefix) as vin_prefix 
    FROM `dealer_monthly_report` d 
    WHERE d.dealerID = 2 
; 

SELECT d.dealerId, sum(d.total_price) 
FROM `dealer_monthly_report` d 
JOIN `vin_prefixes_dealerID_2` d2 
ON d.vin_prefix = d2.vin_prefix 
WHERE d.dealerID <> 2 
GROUP BY d.dealerId; 

Это позволило сократить время на обработку до 0,91 (!!!) секунд

+0

6-7 секунд за 1 миллион записей? У меня 22 миллиона записей в таблице и, возможно, 50 миллионов в конце этого года ..... Любой другой вариант? –

+0

Есть ли какое-то решение из коробки? –

+0

Ну, это было на macbook (2 ГГц Intel Core 2 Duo, 4 ГБ ОЗУ 1067 МГц DDR3 и SSD). Лучшее оборудование, безусловно, улучшит производительность. –

Смежные вопросы