[英]When to add an index on a SQL table field (MySQL)?
我被告知如果你知道你經常使用一個字段進行連接,那么在它上面創建一個索引可能會很好。
我通常理解索引表的概念(很像紙質書中的索引允許您查找特定術語而無需逐頁搜索)。 但我不太清楚何時使用它們。
假設我有3個表:USERS,COMMENTS和VOTES表。 我想創建一個類似Stackoverflow的評論線程,其中查詢返回注釋以及這些注釋上/下投票的數量。
USERS table
user_id user_name
1 tim
2 sue
3 bill
4 karen
5 ed
COMMENTS table
comment_id topic_id comment commenter_id
1 1 good job! 1
2 2 nice work 2
3 1 bad job :) 3
VOTES table
vote_id vote comment_id voter_id
1 -1 1 5
2 1 1 4
3 1 3 1
4 -1 2 5
5 1 2 4
這是在topic_id = 1上返回投票的查詢和SQLFiddle :
select u.user_id, u.user_name,
c.comment_id, c.topic_id, c.comment,
count(v.vote) as totals, sum(v.vote > 0) as yes, sum(v.vote < 0) as no,
my_votes.vote as did_i_vote
from comments c
join users u on u.user_id = c.commenter_id
left join votes v on v.comment_id = c.comment_id
left join votes my_votes on my_votes.comment_id = c.comment_id
and my_votes.voter_id = 1
where c.topic_id = 1
group by c.comment_id, u.user_name, c.comment_id, c.topic_id, did_i_vote;
讓我們假設評論和投票的數量達到數百萬。 為了加快查詢速度,我的問題是我應該在comments.commenter_id
, votes.voter_id
和votes.comment_id
上votes.voter_id
votes.comment_id
嗎?
在SQL表中使用索引的位置並不總是很明確。 但是有一些一般的經驗法則可以幫助您在大多數情況下做出決定。
您應該記住的一般概念是:
編輯
@AndrewLazarus評論非常重要,我決定將其添加到答案中:
這是使用http://www.sqlfiddle.com/#!2/94daa/1使用的一些密鑰的更新
引擎必須將使用索引的成本與不這樣做的成本進行比較。 您會注意到我必須添加更多行才能獲得所使用的索引。
使用索引,引擎必須使用索引來獲取匹配值,這很快。 然后它必須使用匹配來查找表中的實際行。 如果索引沒有縮小行數,那么只需查找表中的所有行就可以更快。
我不確定mysql是否有類似於SQL Server聚簇索引的東西。 在這種情況下,索引和表數據具有相同的結構,因此您沒有索引查找的第二步。
我以兩種不同的方式介紹了索引,首先是通過定義主鍵在users表上。 這將隱式在user_id列上創建唯一索引。 唯一索引意味着您不能兩次插入相同的值集。 對於單列索引,這只意味着您不能兩次具有相同的值。
如果您想象一本桌面的用戶書,每頁有一個用戶,那么創建的索引會為您提供一個user_id的排序列表,每個列表都包含用戶的頁碼。 該列表通常以某種樹形式存儲,以便快速查找特定數字。 考慮一下你在電話簿中查找名字的方式,你不僅要掃描所有頁面,直到找到它,你猜測它會在哪里,然后跳過或轉發大塊的頁面直到你接近。 您通常可以在O(log 2 n)時間內查找索引中的值,其中n是行數,您需要讀取相似數量的索引頁。
現在,如果給DB引擎查詢select * from users Where user_id = 3
,它有兩個選擇。 它可以讀取每個數據頁面,並查找正確的值(它可能會使用主鍵在第一個時停止的事實)。 另一種方法是讀取索引以獲取正確的數據頁,然后查找數據頁。
為了具體和簡單,假設該表有1024個條目。 假設每個條目都占用一個數據頁面。 假設索引樹中的每個條目都占用一個索引頁。 假設索引是平衡的,因此它有10個級別,總共2047個頁面。 (所有這些假設都是可疑的,但是他們得到了相應的點,特別是索引頁幾乎總是小於數據頁,因為你不傾向於一次索引所有列)。
要執行表掃描方法,需要讀取1024個數據頁。 要使用索引,需要讀取10個索引頁和一個數據頁。 幾乎所有數據庫性能都與最小化讀取頁數有關。
多列索引允許快速查找數據集。 如果你有一個索引(col1,col2),即使只是匹配col1也會得到改進。
create index
語句只是說明索引了哪些列,以及是否允許重復值。
再次使用本書類比, Create Index ix_comment_id on votes (comment_id, voter_id)
將創建一個有序的comment_id列表,然后是voter_id,並引用相應的數據行。
+------------+--------------+---------+
| comment_id | reference_id | row_ref |
+------------+--------------+---------+
| 1 | 4 | ref1 |
| 1 | 5 | ref2 |
| 2 | 4 | ref3 |
| 2 | 5 | ref4 |
| 3 | 1 | ref5 |
+------------+--------------+---------+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.