![](/img/trans.png)
[英]MySQL joining tables and returning the latest row from the second table when the comparison is made between identical values
[英]Indexes when left joining 2 tables with order by on second table MySQL
對於有經驗的用戶來說,這可能很容易,但我無法完全理解這個簡單案例需要哪些索引。
除了一些可用於搜索目的的過濾器之外,我有一個可以按任何列排序的前端表:
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 或 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
我看到的第一件事是它正在用戶表中進行全表掃描。 為了避免這種情況,我需要為 users 表創建一個 UNIQUE 索引,其中包含:
id, username, email, name
因此,查詢對 users 表執行 FULL INDEX SCAN。 盡管如此,我發現與按用戶表字段排序相比,查詢成本太高了。
那樣行嗎? 我在這里錯過了什么嗎? 我不確定這是預期結果還是可以改進。
提前致謝
profiles
需要一個以user_id
開頭的索引。 索引中列的順序很重要。
如需進一步討論,請提供SHOW CREATE TABLE
和EXPLAIN FORMAT=JSON SELECT...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.