2014-10-06 2 views
4

Я хочу получить SUM из QTY элемента, сгруппированного по месяцам, запрос занимает слишком много времени (15-20 секунд) для извлечения.Better MySQL Query Performance

-Total строки: 1495873 -Total выбранных строк: 9 - 12

Связь между двумя таблицами (invoice_header и invoice_detail) является (один ко многим), что является invoice_header заголовок счета-фактуры, только с итоги. Что связано с invoice_detail с использованием идентификатора местоположения (loc_id) и номера счета (invo_no), так как каждое место имеет свой собственный серийный номер. Подробная информация о счете-фактуре содержит сведения о каждом счете-фактуре.

Есть ли лучший способ повысить производительность этого запроса, вот это:

SELECT SUM(invoice_detail.qty) AS qty, Month(invoice_header.date) AS month 
FROM invoice_detail 
JOIN invoice_header ON invoice_detail.invo_no = invoice_header.invo_no 
AND invoice_detail.loc_id = invoice_header.loc_id 
WHERE invoice_detail.item_id = {$itemId} 
GROUP BY Month(invoice_header.date) 
ORDER BY Month(invoice_header.date) 

EXPLAIN:

explain

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

CREATE TABLE `invoice_header` (
`invo_type` varchar(1) NOT NULL, 
`invo_no` int(20) NOT NULL AUTO_INCREMENT, 
`invo_code` varchar(50) NOT NULL, 
`date` date NOT NULL, 
`time` time NOT NULL, 
`cust_id` int(11) NOT NULL, 
`loc_id` int(3) NOT NULL, 
`cash_man_id` int(11) NOT NULL, 
`sales_man_id` int(11) NOT NULL, 
`ref_invo_no` int(20) NOT NULL, 
`total_amount` decimal(19,2) NOT NULL, 
`tax` decimal(19,2) NOT NULL, 
`discount_amount` decimal(19,2) NOT NULL, 
`net_value` decimal(19,2) NOT NULL, 
`split` decimal(19,2) NOT NULL, 
`qty` int(11) NOT NULL, 
`payment_type_id` varchar(20) NOT NULL, 
`comments` varchar(255) NOT NULL, 
PRIMARY KEY (`invo_no`,`loc_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=20286 DEFAULT CHARSET=utf8 

invoice_header table structure:

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

CREATE TABLE `invoice_detail` (
`invo_no` int(11) NOT NULL, 
`loc_id` int(3) NOT NULL, 
`serial` int(11) NOT NULL, 
`item_id` varchar(11) NOT NULL, 
`size_id` int(5) NOT NULL, 
`qty` int(11) NOT NULL, 
`rtp` decimal(19,2) NOT NULL, 
`type` tinyint(1) NOT NULL, 
PRIMARY KEY (`invo_no`,`loc_id`,`serial`), 
KEY `item_id` (`item_id`), 
KEY `size_id` (`size_id`), 
KEY `invo_no` (`invo_no`), 
KEY `serial` (`serial`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

invoice_detail table structure:

+1

1. Опубликовать схему для каждой таблицы из запроса 2. 'EXPLAIN' 3. Статистика (полные строки, отфильтрованные строки, мощность индексов, определение« слишком долго »и т. Д.) – zerkms

+0

Ok @zerkms, обновит должность со структурой таблицы 2. – CairoCoder

+0

использовать 'SHOW CREATE TABLE' вместо этого, чтобы он включал все, как индексы. Также - ** все 3 ** предметы ** необходимы **, чтобы помочь вам. Это не похоже на то, что я издеваюсь над вами и спрашиваю какую-то неактуальную информацию, но основные вещи, которые помогут вам. – zerkms

ответ

0

Попробуйте создать несколько индексов в некоторых столбцах: invo_no, LOC_ID, item_id, дата.

Основываясь на вашем объяснении, ваш запрос проверяет все строки в invoice_header. Индексируйте столбцы, которые делают соединение ... invo_no, loc_id

+0

попробует это и посмотрит. – CairoCoder

+0

@CairoCoder: дело в том, что вы либо следуете «процедуре», которая помогает всем вокруг оптимизировать свои базы данных, либо следовать случайным вещам и надеяться, что они будут беспорядочно работать на вас. Это зависит от вас, какой путь следовать. – zerkms

+0

да @zerkms, я должен точно следовать процедуре 4. – CairoCoder

1

Согласно приведенному ниже объяснению, invoice_header не может использовать несколько индексов.

Вы можете создать индекс в поле invo_no на invoice_header Таблица.

+0

Я не понял! не могли бы вы объяснить больше? – CairoCoder

+0

Результат объяснения для таблицы «invoice_header» равен null. Он ищет все строки, которые существуют внутри таблицы «invoice_header». Потому что у него есть только один ключ, который является комбинацией 'invo_no',' loc_id'. для условия «ON invoice_detail.invo_no = invoice_header.invo_no» вы можете создать индекс в поле invoice_header.invo_no для поиска по меньшему количеству строк внутри вложенного цикла соединения. –

1

Сколько времени занимает SQL?

SELECT count(*) 
FROM invoice_detail 
WHERE invoice_detail.item_id = {$itemId} 

Если SQL занимает 15-20 секунд, вы должны добавить индекс на поле item_id на inovice_detail столе.

У счета-фактуры invoice_header уже был первичный ключ в столбцах соединения invo_no и loc_id, поэтому вам не нужно добавлять другие индексы в таблицу invoice_header. Но если вы добавите индекс в поля invo_no, loc_id и date, это может повысить производительность, только сканирование индекса.

+0

ваш запрос занял всего 3 секунды, а после добавления индексов invo_no, loc_id и даты в «invoice_header» и индекса «item_id» в «invoice_detail» теперь основной запрос занимает 8-10 секунд. Любые предложения по его улучшению? – CairoCoder

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

  • Нет связанных вопросов^_^