mysql表应该添加啥样的索引?

Posted

技术标签:

【中文标题】mysql表应该添加啥样的索引?【英文标题】:What kind of index should be added to mysql table?mysql表应该添加什么样的索引? 【发布时间】:2021-04-26 19:11:42 【问题描述】:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
);
  
CREATE TABLE `posts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`message` text NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);

这些是mysql 表,这里是查询。

select COUNT(1)  
from  posts inner 
join users on posts.user_id = users.id  
where email = 'test@gmail.com' 
  and created_at > DATE(NOW() - INTERVAL 30 DAY);

您将向posts 表添加什么样的索引以使该查询有效地工作?

感谢您的任何建议。

【问题讨论】:

外键 user_id 上的索引 【参考方案1】:

由于 UNIQUE KEY,您已经在 users.email 上建立了索引。这将针对您的电子邮件条件优化行选择。

主键users.id 隐含地是索引的一部分,这将用于在posts 中查找匹配的行。

然后您需要在posts 上建立一个索引,以便每个users.id 可以有效地定位匹配的行。索引还应该在created_at 上为范围条件提供第二列。

ALTER TABLE posts ADD INDEX (user_id, created_at);

您可以看到这如何影响 EXPLAIN 并看到使用了索引。

新索引之前:

+----+-------------+-------+------------+-------+---------------+-------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key   | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | users | NULL       | const | PRIMARY,email | email | 1022    | const |    1 |   100.00 | Using index |
|  1 | SIMPLE      | posts | NULL       | ALL   | NULL          | NULL  | NULL    | NULL  |    1 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+-------+---------+-------+------+----------+-------------+

posts 上的连接将被强制执行表扫描。

新索引之后:

+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | users | NULL       | const | PRIMARY,email | email   | 1022    | const |    1 |   100.00 | Using index              |
|  1 | SIMPLE      | posts | NULL       | range | user_id       | user_id | 8       | NULL  |    1 |   100.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+--------------------------+

posts 的连接使用索引。


您可能会喜欢我的演示文稿How to Design Indexes, Really,或者我的演示文稿video。

【讨论】:

以上是关于mysql表应该添加啥样的索引?的主要内容,如果未能解决你的问题,请参考以下文章

mysql 分区的字段 与 where 的条件有啥样的关系啊

多于 1 列的 B 树索引是啥样的?

Oracle中创建了索引,啥样的原因可能使索引不能正常使用?

如果输入一条查询一张表的sql语句,但数据库执行缓慢,如何并采取啥样的方法对数据库进行优化?

mysql 学习 - 掌握单表查询优化

表 Transaction 和 User - Ruby on Rails 应该使用啥样的关系?