2012-08-30 2 views
3

У меня есть 4 таблицы: отгрузки (записи 200K), магазины (45 записей), product_stores (записи 8K), районы (698 записей). Следующий запрос занимает очень много времени для преобразования приложений (12 секунд):Производительность запросов Mysql медленная, нужна помощь в оптимизации

SELECT `s`. * , `p`.`productCode` , `p`.`productName` , `st`.`name` AS `storeName` , `d`.`name` AS `districtName` 
FROM `shipments` AS `s` 
JOIN `product_stores` AS `p` ON s.productStoreId = p.id 
JOIN `stores` AS `st` ON s.storeId = st.id 
LEFT JOIN `districts` AS `d` ON s.districtId = d.id 
WHERE (s.storeId IN (1, 2, 3, 4, 6, 9, 14, 16, 22, 26, 30)) 
GROUP BY `s`.`id` 
ORDER BY `s`.`id` DESC 
LIMIT 100 

EXPLAIN запрос возвращает следующий результат:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE st ALL  PRIMARY  NULL NULL NULL 45 Using where; Using temporary; Using filesort 
1 SIMPLE s ref  fk_shipments_stores1_idx,fk_shipments_product_stor... fk_shipments_stores1_idx 4 st.id 482  
1 SIMPLE p eq_ref PRIMARY  PRIMARY  4 s.productStoreId 1 
1 SIMPLE d eq_ref PRIMARY  PRIMARY  4 s.districtId 1 
  1. Я не знаю, почему MySQL должен Использования временного; Использование filesort в этом случае
  2. Почему mysql не начинается выбор из отгрузок? затем присоединитесь к хранилищу. он начинает выбирать из магазина, а затем присоединяется к отгрузкам? Я пытаюсь запустить EXPLAIN и иногда mysql start select из таблицы product_stores
  3. Пожалуйста, помогите мне оптимизировать таблицу, индексы ... для повышения производительности.

(я использую MySQL 5.0.95)

Это таблица структуры:

+0

Пожалуйста, измените заголовок вопроса на что-то полезное. –

ответ

0

Я просто пытаюсь решение. Надеюсь, что это должно сократить время выполнения

SELECT `s`. * , `ps`.`productCode` , `ps`.`productName` , `st`.`name` AS `storeName` , `d`.`name` AS `shipToDistrictName` 
FROM `shipments` AS `s` 
JOIN `product_stores` AS `ps` ON s.productStoreId = ps.id 
JOIN `stores` AS `st` ON (s.storeId = st.id AND s.storeId IN (1, 2, 3, 4, 6, 9, 14, 16, 22, 26, 30)) 
LEFT JOIN `districts` AS `d` ON s.shipToDistrictId = d.id 
GROUP BY `s`.`id` 
ORDER BY `s`.`id` DESC 
LIMIT 100 

Это ограничит число записей только тех, кто имеет StoreID только те, которые необходимы и в дальнейшем делать соединяется с уменьшенным количеством записей, таким образом, сократить время выполнения.

Надеется, что это помогает ...

+0

Я пробовал это, но все еще 12 -> 14 секунд – Kevin

1

вашего запрос будет достаточно медленным, поскольку ваш запрос присоединения стратегии слишком много I/O

Позволь мне подготовить расчет для запроса ввода/вывода для понимания, как следующие:

1. JOIN shipments (200K records) and product_stores (8K records) 

     200K x 8 K = 1600K I/O 
2. Then, JOIN to stores (45 records) 

     1600K x 45 = 75000K I/O 

3. Then, JOIN to districts (698 records) 

     75000K x 698 = 50256000K I/O 

4. Then, Filter the result (by storeId), so need to read the result I/O again 

     50256000K + 50256000K = **100512000K I/O (TOTAL I/O)** 

So, total I/O on memory of your query is 100512000K I/O. 

чтобы улучшить производительность запроса, вам необходимо пересмотреть свой запрос присоединения плана/стратегии

, например:

1. Read shipments (200K records) and Filter storeId (assume: result is 8 record) 

     200K + 8 = 208K I/O 
2. Then, JOIN to product_stores (8K records) 

     208K x 8K = 1664K I/O 

3. Then, JOIN to stores (45 records) 

     1664K x 45K = 74880K I/O 

4. Then, finally JOIN to districts (698 records). 

     74880K + 698 = **52266240 I/O (TOTAL I/O)** 

So, total I/O on memory of your query is 52266240 I/O. (greatly reduce I/O then ever) 

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

Надеюсь, это может вам помочь.

+0

Спасибо большое. Я изменил INNER JOIN на LEFT JOIN, и теперь он только 0.003sec: SELECT 's'. *, 'ps'.'productCode',' ps'.'productName', 'st'.'name' AS' storeName', 'd'.'name' AS' shipToDistrictName' ОТ 'отгрузки'' '' '' '' LEFT JOIN 'product_stores' AS' ps' ON ​​s.productStoreId = ps.id LEFT JOIN 'хранит' AS 'st' ON (s.storeId = st.id AND st.id IN (1, 2, 3, 4 , 6, 9, 14, 16, 22, 26, 30)) LEFT JOIN 'district' AS' d' ON s.shipToDistrictId = d.id GROUP BY 's'.'id' ЗАКАЗАТЬ BY' s' .'d DESC LIMIT 100 – Kevin

+0

Ваш прием – AKZap

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