2014-10-06 3 views
4

# 항목의 QTY 합계를 월로 설정하려면 쿼리를 가져 오는 데 너무 오래 걸립니다 (15-20 초).더 나은 MySQL 쿼리 성능

- 총 행 : 1,495,873 - 총 반입 행 : 9-12

두 테이블 (invoice_headerinvoice_detail)의 관계가 (일대)에 invoice_header 만에 인보이스의 헤더임을 합계. 위치 ID (loc_id) 및 송장 번호 (invo_no)를 사용하여 각 위치에 고유 한 일련 번호가있는 invoice_detail에 연결됩니다. 송장 세부 사항에는 각 송장의 세부 사항이 들어 있습니다.

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

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은 다중 인덱스를 사용할 수 없습니다.

invoice_header 표에 invo_no 필드에 색인을 생성 할 수 있습니다.

+0

나는 요점을 얻지 않았다! 더 설명해 주시겠습니까? – CairoCoder

+0

"invoice_header"테이블에 대한 explain 결과는 null입니다. 그것은 "invo_no','loc_id'의 조합 인 오직 하나의 키만 가지고 있기 때문에"invoice_header "테이블 안에 존재하는 모든 행을 검색합니다. "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 초가 소요되면 inovice_detail 테이블의 item_id 필드에 색인을 추가해야합니다.

invoice_header에는 이미 invo_no 및 loc_id 조인 열에 기본 키가 있으므로 invoice_header 테이블에 다른 인덱스를 추가 할 필요가 없습니다. 그러나 invo_no, loc_id 및 date 필드에 색인을 추가하면 색인 스캔만으로 성능이 향상 될 수 있습니다.

+0

쿼리를 실행하는 데 3 초 밖에 걸리지 않았습니다. invo_no에 loc_id와 date를 추가 한 후 "invoice_detail"의 "invoice_header"및 index "item_id"에 현재 주 쿼리가 8-10 초 걸립니다. 더 많은 개선 제안은 없습니까? – CairoCoder