2017-05-23 6 views
0

가입에 나는 다음과 같은 MySQL의 테이블 (전용 845 행)이 있습니다 MySQL의 - 전체 테이블 스캔 쿼리

CREATE TABLE `categories_nested_set` (
    `lft` int(11) NOT NULL DEFAULT '0', 
    `rgt` int(11) DEFAULT NULL, 
    `id` int(11) DEFAULT NULL, 
    `category` varchar(128) DEFAULT NULL, 
    PRIMARY KEY (`lft`), 
    UNIQUE KEY `id` (`id`), 
    UNIQUE KEY `rgt` (`rgt`), 
    KEY `idx_lftrgtid` (`id`,`lft`,`rgt`), 
    KEY `idx_lft` (`lft`), 
    KEY `i1` (`lft`) USING BTREE, 
    KEY `i2` (`rgt`) USING BTREE, 
    KEY `i3` (`id`) USING BTREE, 
    CONSTRAINT `fk_categories_nested_set_id_category` FOREIGN KEY (`id`) REFERENCES `categories` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

가 (당신이 단지의 경우, 내가 거기에 인덱스의 전체 많이 볼 수 있습니다).

나는 다음과 같은 자체 조인 쿼리를 수행 생성

SELECT * 
FROM categories_nested_set  AS H 
LEFT JOIN categories_nested_set AS I ON (H.lft > I.lft) 

을 다음 EXPLAIN :

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra 
1,SIMPLE,H,ALL,NULL,NULL,NULL,NULL,845,NULL 
1,SIMPLE,I,ALL,"PRIMARY,idx_lft,i1",NULL,NULL,NULL,845,"Range checked for each record (index map: 0x31)" 

enter image description here

은 MySQL이 사용하지 않는 선택하는 것을 제안 EXPLAIN 색인, 나는 왜 이해할 수 없다. 테이블 정의는 모든 관련 컬럼이 인덱싱됨을 보여줍니다.

엄청난 규모의 쿼리 (5 백만 행, 14x 테이블)의 범위에서이 부분은 막대한 병목 현상을 일으키는 것으로 입증되었습니다. 어떤 조언을 주시면 감사하겠습니다.

감사합니다,

+0

'EXPLAIN'을 실행 한 데이터 세트에는 실제로 845 개의 행만 있습니까? 예를 들어 데이터 세트가 충분히 작은 경우, MySQL은 인덱스를 반드시 사용할 필요는 없습니다. 실제보다 큰 쿼리에 대한 성능 통계를 얻어야합니다. –

+0

예, 단지 845 행. 큰 쿼리에 대해 다른 설명을하면 훨씬 더 정교하지만 그럼에도 불구하고 전체 테이블 검색. – mils

+0

조인의 왼쪽에있는 표에 대해 전체 표 스캔을 하나 이상 수행해야합니다. –

답변

0

난 당신이 쿼리를 사용한다고 생각 :

SELECT * FROM categories_nested_set AS H , categories_nested_set AS I where (H.lft > I.lft); 

아이디어는 한 번에 하나 개의 행을 일치시켜 결과를 구성하기 위해 MySQL을 강제하기 때문에 가입 사용하지 않는 것입니다.

교차 제품 테이블은 조인없이 구성되므로 InnoDB는 다른 테이블과 독립적으로 첫 번째 테이블 (H)에서 행을 가져와 행을 일괄 처리 할 수 ​​있습니다. 두 번째 테이블의 인덱스는 H 테이블과 링크가 없기 때문에 MySQL에서 사용할 수 있습니다.

내 컴퓨터에서 제안 된 솔루션은 1000 레코드의 테이블로 약 5 배 빠릅니다. 당신은 또한 (즉, 항상 그런 것은 아니지만)이 검색되는 열을 제한하여 요청의 인덱스 사용을 향상시킬 수

EXPLAIN SELECT * FROM categories_nested_set AS H , categories_nested_set AS I where (H.lft > I.lft); 

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE H ALL PRIMARY,idx_lft,i1 NULL NULL NULL 921 
1 SIMPLE I ALL PRIMARY,idx_lft,i1 NULL NULL NULL 921 Using where; Using join buffer 

참고 : 여기에

는 설명의 결과입니다.

+0

그러나이 쿼리는 많은 조합을 생성하기 때문에 호기심에 의해서만이 쿼리를 사용하여 중첩 된 트리 구조에서 무엇을 추출하려고합니까? 내가 이해하는 것으로부터 하나가 다른 노드의 모든 노드 쌍이지만, 당신이 그걸로 무엇을 할 것인가를 얻지 못했습니다 ... 감사합니다 –

+0

안녕하세요 아르노, 아직 답을 읽고 계시지 만, 실제 질의는 전형적인 중첩 된 집합 쿼리이다 '좌' ON I (I.lft AND I.rgt BETWEEN H.lft)와 같은 가입 categories_nested_set H = ON H.id C.id_category AS categories_nested_set 가입 LEFT 하지만 나는이 문제에 대해 혼란을 없애고 싶었습니다. – mils

+0

동일한 질문을 실행했는데 여기에 EXPLAIN이 있습니다 : 'id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra 1, SIMPLE, H, ALL, "PRIMARY, idx_lft, i1", NULL, NULL, NULL, 845, NULL 1, 단순함, 전체, "PRIM ARY, idx_lft, i1 ", NULL, NULL, NULL, 845,"각 레코드 (인덱스 맵 : 0x31)에 대한 범위 검사 " – mils