MySql - JOIN查询的全表扫描

时间:2017-05-23 04:00:08

标签: mysql join indexing hierarchical-data full-table-scan

我有以下MySql表(只有845行):

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

EXPLAIN会建议MySql选择不使用索引,我不明白为什么。表定义显示所有相关列都已编制索引。

在一个更大的查询(500万行,14x表)的范围内,这件作品被证明是一个巨大的瓶颈。任何建议将不胜感激。

谢谢,

2 个答案:

答案 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表中建立链接。

在我的电脑上,建议的解决方案速度提高了约5倍,其中包含1000条记录。

以下是解释的结果:

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

请注意,您还可以通过限制要检索的列来改进请求的索引使用(尽管并非总是如此)。

答案 1 :(得分:0)

LEFT JOIN 匹配表中的所有字段。尝试使用 INNER JOIN 而不是它。