有这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
)进行全表扫描。我的意思是,只有两个用户需要检索有关的数据(标识为1
和2
),这两个用户可以通过主键user_id
找到。有经验的人可以帮我理解这个吗?是否有更好的方法来创建索引,以便MySQL不必在users
表上进行完整扫描以检索有关帖子作者的数据?
谢谢!
答案 0 :(得分:2)
根据您的测试数据和EXPLAIN报告,您users
表中只有~3行。
如果表中的行太少,优化程序可能会产生偏差结果。它可以对一个小表进行表扫描,即使它会针对具有几百行或几千行的相同表使用相同查询的索引。
因此,在进行开发时,如果您希望获得准确的优化程序报告,则在表中包含大量的测试数据非常重要。
答案 1 :(得分:2)
因此,如此少量的索引搜索将比顺序搜索慢。因此MySQL选择使用简单的表读取。
这与运营效率有关。让我们简单地说明MySQL必须做的操作来读取整个表与使用索引。
完整阅读:
这是5次操作。
索引阅读
在这种情况下有8次操作。
这是非常简化的,但除非您有足够的数据,否则您的索引会降低您的速度。随着表的增长,MySQL可能会选择不同的查询路径。这就是为什么你不强迫使用索引。