【发布时间】:2021-07-22 10:51:19
【问题描述】:
对于有经验的用户来说这可能很容易,但我无法完全理解这个简单案例需要哪些索引。
除了一些可用于搜索目的的过滤器之外,我有一个可以按任何列排序的前端表:
id | username | email | name | phone | email_verified_at
显示的行是连接 2 个表的结果(具有一对一关系):
TABLE USERS
id | autoincrement
name | string
username | string | unique
email | string | unique
email_verified_at | timestamp | nullable
INDEXES
primary(id)
unique(name,id)
unique(username)
unique(email)
unique(email_verified_at,email)
TABLE PROFILES
id | autoincrement
user_id | FK(users)
phone | string
INDEXES
primary(id)
index(user_id)
unique(phone,user_id)
最基本的查询,按用户id排序
select
`users`.`id` as `id`,
`users`.`name` as `name`,
`users`.`username` as `username`,
`users`.`email` as `email`,
`users`.`email_verified_at` as `email_verified_at`,
`profiles`.`phone` as `phone`
from
`users`
left join `profiles` on `users`.`id` = `profiles`.`user_id`
order by
`id` asc
limit
11
按 id、姓名、用户名、电子邮件或 email_verified_at 排序在用户表中执行全索引扫描,我认为这是正确的。
但是当我尝试通过电话订购时,麻烦(或没有)来了:
select
`users`.`id` as `id`,
`users`.`name` as `name`,
`users`.`username` as `username`,
`users`.`email` as `email`,
`users`.`email_verified_at` as `email_verified_at`,
`profiles`.`phone` as `phone`
from
`users`
left join `profiles` on `users`.`id` = `profiles`.`user_id`
order by
`phone` asc
limit
11
我看到的第一件事是它正在用户表中进行全表扫描。 为了避免我需要为包含以下内容的用户表创建一个唯一索引:
id, username, email, name
因此,查询对用户表执行全索引扫描。 尽管如此,与按用户表字段排序相比,我发现查询成本太高了。
这样好吗?我在这里错过了什么吗?我不确定这是预期结果还是可以改进。
提前致谢
【问题讨论】:
标签: php mysql indexing left-join