EXPLAIN SELECT ..,为什么TYPE = ALL?

时间:2013-08-22 21:56:59

标签: mysql

有这3个表:

用户

CREATE TABLE `users` (
    `user_id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
    `first_name` VARCHAR(64) NOT NULL,
    `last_name` VARCHAR(64) NOT NULL,
    PRIMARY KEY (`user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;

帖子

CREATE TABLE `posts` (
    `post_id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
    `category_id` MEDIUMINT(8) UNSIGNED NOT NULL,
    `author_id` MEDIUMINT(8) UNSIGNED NOT NULL,
    `title` VARCHAR(128) NOT NULL,
    `text` TEXT NOT NULL,
    PRIMARY KEY (`post_id`),
    INDEX `FK_posts__category_id` (`category_id`),
    INDEX `FK_posts__author_id` (`author_id`),
    CONSTRAINT `FK_posts__author_id` FOREIGN KEY (`author_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE,
    CONSTRAINT `FK_posts__category_id` FOREIGN KEY (`category_id`) REFERENCES `categories` (`category_id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;

类别

CREATE TABLE `categories` (
    `category_id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(64) NOT NULL,
    PRIMARY KEY (`category_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;

表中的数据:

INSERT INTO `users` (`user_id`, `first_name`, `last_name`) VALUES
    (1, 'John', 'Doe'),
    (2, 'Pen', 'Poe'),
    (3, 'Robert', 'Roe');

INSERT INTO `categories` (`category_id`, `name`) VALUES
    (1, 'Category 1'),
    (2, 'Category 2'),
    (3, 'Category 3'),
    (4, 'Category 4');

INSERT INTO `posts` (`post_id`, `category_id`, `author_id`, `title`, `text`) VALUES
    (1, 1, 1, 'title 1', 'text 1'),
    (2, 1, 2, 'title 2', 'text 2');

我想做一个简单的选择(让MySQL解析它):

EXPLAIN SELECT p.post_id, p.title, p.text, c.category_id, c.name, u.user_id, u.first_name, u.last_name
FROM posts AS p
JOIN categories AS c
ON c.category_id = p.category_id
JOIN users AS u
ON u.user_id = p.author_id
WHERE p.category_id = 1

我明白了:

enter image description here

我不明白的是,为什么MySQL要在uusers)进行全表扫描。我的意思是,只有两个用户需要检索有关的数据(标识为12),这两个用户可以通过主键user_id找到。有经验的人可以帮我理解这个吗?是否有更好的方法来创建索引,以便MySQL不必在users表上进行完整扫描以检索有关帖子作者的数据?

谢谢!

2 个答案:

答案 0 :(得分:2)

根据您的测试数据和EXPLAIN报告,您users表中只有~3行。

如果表中的行太少,优化程序可能会产生偏差结果。它可以对一个小表进行表扫描,即使它会针对具有几百行或几千行的相同表使用相同查询的索引。

因此,在进行开发时,如果您希望获得准确的优化程序报告,则在表中包含大量的测试数据非常重要。

答案 1 :(得分:2)

因此,如此少量的索引搜索将比顺序搜索慢。因此MySQL选择使用简单的表读取。

这与运营效率有关。让我们简单地说明MySQL必须做的操作来读取整个表与使用索引。

完整阅读:

  1. 打开桌子
  2. 一次阅读每一行并符合条件
  3. 返回结果集
  4. 这是5次操作。

    索引阅读

    1. 打开桌子
    2. 对于标准,请阅读每行的索引
    3. 使用索引指针在磁盘上找到每行的行
    4. 返回结果集
    5. 在这种情况下有8次操作。

      这是非常简化的,但除非您有足够的数据,否则您的索引会降低您的速度。随着表的增长,MySQL可能会选择不同的查询路径。这就是为什么你不强迫使用索引。