2017-05-23 56 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) 

產生以下講解:

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

的EXPLAIN會建議MySQL是選擇不使用索引,我不明白爲什麼。表定義顯示所有相關的列都被編入索引。

在一個更大的查詢(500萬行,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); 

的想法是不使用JOIN,因爲它強制MySQL通過一次匹配一行來構造的結果。

在我建議的解決方案中,跨產品表的構建沒有聯接,因此它使InnoDB能夠獨立於其他表從第一個表(H)中獲取行,從而允許它進行批處理行。第二張表上的索引可以被MySQL使用,因爲H表中沒有鏈接。

在我的計算機上,建議的解決方案比使用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

然而,僅僅因爲好奇心,因爲這個查詢產生了很多組合,你真正嘗試從這個查詢中嵌套集合樹結構中提取什麼?根據我的理解,當一個接一個接一個時,所有的節點對都可以,但是我不明白你會怎麼做...... THanks –

+0

嗨Arnaud,我仍在閱讀你的答案,但是你的問題重提,真正的查詢是一個典型的組嵌套查詢: '左連接categories_nested_set爲h ON H.id = C.id_category LEFT JOIN categories_nested_set AS I ON(H.lft BETWEEN I.lft AND I.rgt)' 但我想消除任何關於BETWEEN性能的混淆 – mils

+0

只是跑了你的查詢,同樣的問題,這裏是解釋: 'id,select_type,table,type,possible_keys,key,key_len,ref,rows,額外 1, SIMPLE,H,ALL,「PRIMARY,idx_lft,i1」,NULL,NULL,NULL,845,NULL 1,SIMPLE,I,ALL,「PRIM ARY,idx_lft,i1「,NULL,NULL,NULL,845,」每個記錄的檢查範圍(索引映射:0x31)「' – mils