mysqll索引實驗
什麼是資料庫索引?
索引是對資料庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問資料庫表中的特定資訊。如果想按特定職員的姓來查詢他或她,則與在表中搜索所有的行相比,索引有助於更快地獲取資訊。
簡單來說,索引就是一種排序的資料結構,資料庫中的資料無序,但是這種結構是有序的,這種有序的結構指向資料庫中的資料,使得資料在邏輯上是有序的(但是實際的儲存仍然是無序的)。
利用這種邏輯上的有序性 ,可以更快的進行查詢 ,否則必須進行全表掃描 。
全表掃描的時間複雜度是O(n),這是一個看起來還不錯的複雜度。然而資料庫中的資料往往是儲存在外儲存器上的,並且這些資料也無法一次性全部調入記憶體,那麼如果全表掃描必然出現多次的訪問外存操作,這是一個極度耗時的操作,把這些資料調入記憶體所花費的時間甚至比在記憶體中掃描這些資料花費的時間多得多 。這使得O(n)複雜度的時間規模 在這裡已經不適用了!!!
利用索引 這種有序結構不僅可以減少比較次數(不再是全表掃描),而且還可以減少訪問外存的次數,這樣一來,時間大大縮短 。
下面來做試驗。
現在有一張資訊表user,表結構為:
name,id,age,position
其中name代表使用者名稱字,id代表使用者賬戶,age代表使用者年齡,position代表使用者職位。
這張表有100000條資料。
現在我們不加索引 查詢年齡為30歲的人數。
結果:
select count(*) from user where age = 32
受影響的行: 0
時間: 0.015s
然後新增索引:
CREATE INDEX myIndex ON user(age)
再查詢一次:
受影響的行: 0
時間: 0.001s
發現時間為原來的1/15 !!!
這大大加快了查詢的速度!!!
不過索引也並非全是優點。
為了維護索引的有序性,在新增或者刪除資料的時候會造成很大的時間損耗。
比如我們現在插入一條資料
**insert into user(name,age,position) VALUES('未命名',29,'老師')
受影響的行: 1
時間: 0.094s**
現在我們刪除索引再新增資料:
刪除索引:ALTER TABLE user DROP INDEX myIndex
插入資料:
insert into user(name,age,position) VALUES('未命名',20,'老師')
受影響的行: 1
時間: 0.016s
可以發現有索引的時候插入資料的耗時非常大,並且這是隻有兩個索引的時候(主鍵索引和剛才新增的age列的索引)如果索引較多,那麼耗時則會更大!!!
最後,索引實際上是為了查詢優化而誕生的技術,它可以大大減少查詢的時間,但是也會大大增加增刪改的時間,因此並不是建立索引就一定能使得系統性能得到提升,因為系統的時間不僅取決於查詢的時間,也取決於增刪改的時間。
一般來說,不應該建立索引的這些列具有下列特點:
第一,對於那些在查詢中很少使用或者參考的列不應該建立索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。
第二,對於那些只有很少資料值的列也不應該增加索引。這是因為,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的資料行佔了表中資料行的很大比例,即需要在表中搜索的資料行的比例很大。增加索引,並不能明顯加快檢索速度。
第三,對於那些定義為text, image和bit資料型別的列不應該增加索引。這是因為,這些列的資料量要麼相當大,要麼取值很少,不利於使用索引。
第四,當修改效能遠遠大於檢索效能時,不應該建立索引。這是因為,修改效能和檢索效能是互相矛盾的。當增加索引時,會提高檢索效能,但是會降低修改效能。當減少索引時,會提高修改效能,降低檢索效能。因此,當修改操作遠遠多於檢索操作時,不應該建立索引。