0

有这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

我懂了:

在此处输入图像描述

我不明白的是,为什么 MySQL 要在u( users) 处进行全表扫描。我的意思是只有两个用户必须检索有关(使用 id12)的数据,而这两个用户可以通过 primary key 找到user_id。有更多经验的人可以帮助我理解这一点吗?有没有更好的方法来创建索引,这样 MySQL 就不必对users表进行全面扫描来检索有关帖子作者的数据?

谢谢!

4

2 回答 2

2

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

这与这里的运营效率有关。让我们简单地了解 MySQL 读取整个表与使用索引所必须执行的操作。

全文阅读:

  1. 打开表
  2. 一次读取每一行并匹配标准
  3. 返回结果集

也就是5个操作。

索引读取

  1. 打开表
  2. 对于标准,请阅读每行的索引
  3. 使用索引指针为每一行定位磁盘上的行
  4. 返回结果集

在这种情况下,有 8 次操作。

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

于 2013-08-22T22:06:20.197 回答
2

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

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

因此,在进行开发时,如果您想获得准确的优化器报告,那么在您的表中拥有大量的测试数据非常重要。

于 2013-08-22T22:04:17.580 回答